You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
(5) |
Apr
(5) |
May
(23) |
Jun
|
Jul
(11) |
Aug
(3) |
Sep
(1) |
Oct
(8) |
Nov
(24) |
Dec
(3) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(17) |
Feb
(5) |
Mar
(18) |
Apr
(10) |
May
(4) |
Jun
(5) |
Jul
(67) |
Aug
(7) |
Sep
(4) |
Oct
(2) |
Nov
(4) |
Dec
(9) |
| 2004 |
Jan
(16) |
Feb
(4) |
Mar
(7) |
Apr
(5) |
May
(4) |
Jun
(5) |
Jul
(3) |
Aug
(3) |
Sep
(3) |
Oct
(8) |
Nov
|
Dec
|
| 2005 |
Jan
(5) |
Feb
(6) |
Mar
(4) |
Apr
(1) |
May
(2) |
Jun
(2) |
Jul
(1) |
Aug
|
Sep
(5) |
Oct
(1) |
Nov
|
Dec
(7) |
| 2006 |
Jan
(10) |
Feb
(4) |
Mar
(10) |
Apr
(8) |
May
(8) |
Jun
(14) |
Jul
(7) |
Aug
(4) |
Sep
(4) |
Oct
(24) |
Nov
(29) |
Dec
(10) |
| 2007 |
Jan
(5) |
Feb
(12) |
Mar
(11) |
Apr
(10) |
May
(3) |
Jun
(3) |
Jul
(15) |
Aug
(28) |
Sep
(8) |
Oct
(5) |
Nov
(8) |
Dec
(13) |
| 2008 |
Jan
(7) |
Feb
(11) |
Mar
(29) |
Apr
(28) |
May
(17) |
Jun
(9) |
Jul
(18) |
Aug
(7) |
Sep
(8) |
Oct
(9) |
Nov
(11) |
Dec
(53) |
| 2009 |
Jan
(112) |
Feb
(19) |
Mar
(46) |
Apr
(32) |
May
(90) |
Jun
(91) |
Jul
(33) |
Aug
(11) |
Sep
(16) |
Oct
(23) |
Nov
(15) |
Dec
(3) |
| 2010 |
Jan
(1) |
Feb
|
Mar
(37) |
Apr
(47) |
May
(66) |
Jun
(69) |
Jul
(29) |
Aug
(45) |
Sep
(23) |
Oct
(3) |
Nov
(1) |
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
| 2012 |
Jan
|
Feb
|
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2013 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
(2) |
Jun
(1) |
Jul
(3) |
Aug
(6) |
Sep
(1) |
Oct
(7) |
Nov
(1) |
Dec
(1) |
| 2014 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(1) |
| 2015 |
Jan
(2) |
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
(3) |
| 2016 |
Jan
(4) |
Feb
(5) |
Mar
(2) |
Apr
|
May
|
Jun
(2) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(2) |
Dec
(1) |
| 2017 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2018 |
Jan
|
Feb
(1) |
Mar
(25) |
Apr
(3) |
May
(1) |
Jun
(2) |
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
(5) |
Dec
(1) |
| 2019 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
(1) |
Jun
(4) |
Jul
(3) |
Aug
|
Sep
(3) |
Oct
(6) |
Nov
(1) |
Dec
|
| 2020 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(1) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2022 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
(1) |
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
(1) |
| 2023 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
| 2024 |
Jan
(2) |
Feb
(2) |
Mar
(5) |
Apr
(2) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2025 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(2) |
Sep
(4) |
Oct
|
Nov
|
Dec
|
|
From: <it...@it...> - 2003-07-30 19:47:42
|
尊敬的各位朋友:
山东省是中国经济最发达的地区,也是最大的IT产品市
场之一,每年有1000亿元的市场采购,是中国北方地区最大
(北京除外)的区域市场。
为了发展你们的事业,获得更多的市场机会,我们
热情邀请您参加'2003中国国际信息技术博览会暨城市信息
化市长论坛。
中国国际信息技术博览会(ITEXPO)是山东省规模最大、
效果最好,也是唯一由政府主办和承办的IT盛会。该会以观
众层次高、展览效果好、服务体贴周到而闻名遐迩,成为众
多IT企业进军齐鲁大地的首要选择。IBM、CISCO、HP、MICROSOFT、
西门子、爱立信、诺基亚等世界著名IT跨国集团和华为、联
想、方正、神州数码、浪潮等国内IT知名企业均通过参加展
览,顺利打开山东市场。ITEXPO自从1999年开展以来,已经
有70万观众参观,达成交易上百亿元。
2003年山东省各行业、各部门、各企业全面加大信息化
投资力度,并在本届展会上选择合作单位,请抓住这个宝贵
的机会,到济南开辟更大的事业!
中国国际信息技术博览会 诚邀
2003、7、28
时间: 2003年10月16日――10月19日(周四--周日)
大会组委会设在济南市人民政府信息化办公室
地址:[250001]济南市纬二路182号
济南市人民政府信息化办公室
电话:86-531-2075611
传真:86-531-2075606
手机:13505410459
联系人:路晨曦
由于展位特别紧张,请火速预订。详细资料可来电索取。
http://www.ITexpo.com.cn
http://www.jn.gov.cn
mailto:it...@jn...
|
|
From: Fred L. D. <fd...@us...> - 2003-07-21 18:09:14
|
Update of /cvsroot/cvs-syncmail/syncmail/doc In directory sc8-pr-cvs1:/tmp/cvs-serv2203 Added Files: branchctl.1 branchctl.sgml Log Message: Manual page for branchctl. --- NEW FILE: branchctl.1 --- .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng <st...@gg...>. .TH "BRANCHCTL" "1" "21 July 2003" "" "" .SH NAME branchctl \- Control access to CVS repositories by branch .SH SYNOPSIS \fBbranchctl\fR [ \fB--config \fIfile\fB\fR ] [ \fB--no-config\fR ] [ \fB--cvsroot \fIpath\fB\fR ] [ \fB--help | -h\fR ] .SH "DESCRIPTION" .PP \fBbranchctl\fR takes care of disallowing checkins for branches that have been marked "off-limits". .PP In any large project using CVS branches, some branches will be active, some will have been merged into other branches or the trunk, and others will have been bypassed. CVS really does not provide tools to make easy to determine which branches are still being used, and it's easy for someone new to a project to find an interesting tangent in a branch and start working on it, even though the branch has been abandoned or has already been merged into another branch where the features of the original branch are to be maintained. .PP CVS also allows a single commit to affect files on more than one branch; this is possible by committing two files in one working directory after using \fBcvs up -r\fR to move one of them to a different branch. \fBbranchctl\fR allows the repository administrator to disallow such commits. .PP branchctl works by integrating with CVS in the repository using the configuration files in the repository's CVSROOT module. When CVS executes commands from the \fIcommitinfo\fR file, branchctl is invoked if it has been configured. .SH "SETTING UP BRANCHCTL" .PP Setting up branchctl is not difficult, but there are usually several steps: .TP 3 1. Install branchctl. This is usually done by adding it to your CVS repository, but it may be located in a directory on the default \fBPATH\fR, or just about anywhere else. .TP 3 2. Configure CVS to invoke branchctl. This is a matter of adding and/or changing some of the configuration files in the CVSROOT module in the repository. .SS "INSTALL BRANCHCTL" .PP branchctl consists of a single Python script; it does not need any supplemental data files. There are two approaches to installing the script: check it into the repository, or place it in a shared location on the CVS server. .PP To install branchctl by checking it into the repository itself, check out a working copy of the CVSROOT module. Add the name branchctl to the file \fIcheckoutlist\fR in that directory as well, and commit that change. This will cause a copy of branchctl to be checked out into the repository itself. Copy te branchctl script into the directory, make sure that it is executable by everyone (you should use \fBchmod a+x branchctl\fR for this), and use the \fBcvs add\fR and \fBcvs commit\fR commands to add it to the repository. Once the commit is complete, a checked-out copy of the branchctl script should be located in the repository in the \fICVSROOT\fR directory in the repository. This is the usual way of integrating branchctl into a CVS repository. .PP To install branchctl outside of the repository, find a location for the script. This can be in a "bin" directory such as \fI/usr/local/bin/\fR, or can be in some other location. The only requirement is that all users of the repository be able to execute the script (you should use \fBchmod a+x branchctl\fR for this). This approach requires direct access to the CVS server machine, and is most useful if several repositories are going to share a single copy of branchctl (maybe to ensure the same version is used for each; it's not large enough for disk space to be an issue). .SS "CONFIGURE CVS TO USE BRANCHCTL" .PP Getting the CVS server to invoke branchctl requires editing one more file in the \fICVSROOT\fR module of the repository. Even if you're using a shared installation of branchctl, this configuration needs to be performed for each repository. .PP The \fIcommitinfo\fR file in the \fICVSROOT\fR module needs to be modified to invoke branchctl when appropriate. Just when is appropriate depends entirely on your project. If your \fIcommitinfo\fR file still contains the comments that \fBcvs init\fR copies in, this is a good time to read them if you haven't. If the file does not already contain any configuration lines, you can simply add to the end of the file. .PP Here are some example lines to get you started: .nf DEFAULT $CVSROOT/CVSROOT/branchctl ProjectOne $CVSROOT/CVSROOT/branchctl --no-config ProjectTwo $CVSROOT/CVSROOT/branchctl --config project-two.conf .fi .PP The first line causes the default configuration file, \fIbranchctl.conf\fR, to be used everywhere that doesn't use an alternate invocation of branchctl. .PP The second line tells CVS to use branchctl's internal configuration defaults instead of reading a configuration file, but to only do so in the the \fIProjectOne\fR directory of the repository. .PP The third line tells CVS to run branchctl using a separate configuration file for the \fIProjectTwo\fR directory in the repository. .PP To finish the repository configuration, commit the changes you've made. Once the CVS server has reported that it is "Rebuilding administrative file database", your repository is configured to use branchctl. .SH "OPTIONS" .PP When an option includes an argument, you may specify the argument either separate ("-d output") or mashed ("-doutput"). branchctl supports both. For long options which include an argument, the argument may be separated from the option ("--fromhost example.com") or mashed, but with an equals sign between the option and the argument ("--fromhost=example.com"). .TP \fB--config \fIfile\fB\fR Use \fIfile\fR as the configuration file for branchctl. By default, a file named \fIbranchctl.conf\fR is used if it exists. If the name of the configuration file is relative, it is interpreted as relative to the \fICVSROOT\fR administrative directory of the repository. \fB--config\fR is incompatible with \fB--no-config\fR. .TP \fB--no-config\fR Do not use a configuration file for branchctl. This can be used to disable the use of the default configuration file. \fB--no-config\fR is incompatible with \fB--config\fR. Note that it's not normally useful to specify this option, but it may be useful when you want to allow changes to any branch within a single CVS module, but use a more sophisticated configuration for the rest of the repository. .TP \fB--cvsroot \fIpath\fB\fR Use \fIpath\fR as the value for the \fBCVSROOT\fR environment variable. This is usually not needed. .TP \fB--help\fR .TP \fB-h\fR Print a summary of the command line options to standard output. .SH "BUGS" .PP There are probably some bugs. If you find them, please report them to the maintainers using the bug tracker <URL:http://sourceforge.net/projects/cvs-syncmail/>. .SH "SEE ALSO" .PP The branchctl page <URL:http://sourceforge.net/projects/cvs-syncmail/> on SourceForge <URL:http://sourceforge.net/>. .PP The CVS home page <URL:http://www.cvshome.org/>. .SH "AUTHOR" .PP branchctl was originally written by Fred Drake. .PP This manual page was written by Fred L. Drake, Jr. <fd...@ac...>. --- NEW FILE: branchctl.sgml --- <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [ <!-- Process this file with docbook-to-man to generate an nroff manual page: `docbook-to-man manpage.sgml > manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ --> <!-- Fill in your name for FIRSTNAME and SURNAME. --> <!ENTITY dhfirstname "<firstname>Fred</firstname>"> <!ENTITY dhsurname "<surname>Drake</surname>"> <!-- Please adjust the date whenever revising the manpage. --> <!ENTITY dhdate "<date>July 14, 2003</date>"> <!-- SECTION should be 1-8, maybe w/ subsection other parameters are allowed: see man(7), man(1). --> <!ENTITY dhsection "<manvolnum>1</manvolnum>"> <!ENTITY dhemail "<email>fd...@ac...</email>"> <!ENTITY dhusername "Fred L. Drake, Jr."> <!ENTITY dhucpackage "<refentrytitle>branchctl</refentrytitle>"> <!ENTITY dhpackage "branchctl"> <!ENTITY debian "<productname>Debian GNU/Linux</productname>"> <!ENTITY gnu "<acronym>GNU</acronym>"> <!ENTITY sourceforge "<ulink url='http://sourceforge.net/'>SourceForge</ulink>"> ]> <refentry> <refentryinfo> <address> &dhemail; </address> <author> &dhfirstname; &dhsurname; </author> <copyright> <year>2003</year> <holder>&dhusername;</holder> </copyright> &dhdate; </refentryinfo> <refmeta> &dhucpackage; &dhsection; </refmeta> <refnamediv> <refname>&dhpackage;</refname> <refpurpose>Control access to CVS repositories by branch</refpurpose> </refnamediv> <refsynopsisdiv> <cmdsynopsis> <command>&dhpackage;</command> <arg>--config <replaceable>file</replaceable></arg> <arg>--no-config</arg> <arg>--cvsroot <replaceable>path</replaceable></arg> <arg><option>--help</option> | <option>-h</option></arg> </cmdsynopsis> </refsynopsisdiv> <refsect1> <title>Description</title> <para> <command>&dhpackage;</command> takes care of disallowing checkins for branches that have been marked "off-limits". </para> <para> In any large project using CVS branches, some branches will be active, some will have been merged into other branches or the trunk, and others will have been bypassed. CVS really does not provide tools to make easy to determine which branches are still being used, and it's easy for someone new to a project to find an interesting tangent in a branch and start working on it, even though the branch has been abandoned or has already been merged into another branch where the features of the original branch are to be maintained. </para> <para> CVS also allows a single commit to affect files on more than one branch; this is possible by committing two files in one working directory after using <command>cvs up -r</command> to move one of them to a different branch. <command>&dhpackage;</command> allows the repository administrator to disallow such commits. </para> <para> &dhpackage; works by integrating with CVS in the repository using the configuration files in the repository's CVSROOT module. When CVS executes commands from the <filename>commitinfo</filename> file, &dhpackage; is invoked if it has been configured. </para> </refsect1> <refsect1> <title>Setting Up branchctl</title> <para> Setting up &dhpackage; is not difficult, but there are usually several steps: </para> <orderedlist numeration="arabic"> <listitem> <para> Install &dhpackage;. This is usually done by adding it to your CVS repository, but it may be located in a directory on the default <envar>PATH</envar>, or just about anywhere else. </para> </listitem> <listitem> <para> Configure CVS to invoke &dhpackage;. This is a matter of adding and/or changing some of the configuration files in the CVSROOT module in the repository. </para> </listitem> </orderedlist> <refsect2> <title>Install &dhpackage;</title> <para> &dhpackage; consists of a single Python script; it does not need any supplemental data files. There are two approaches to installing the script: <simplelist type="inline"> <member>check it into the repository</member> <member>or place it in a shared location on the CVS server</member> </simplelist>. </para> <para> To install &dhpackage; by checking it into the repository itself, check out a working copy of the CVSROOT module. Add the name <literal>&dhpackage;</literal> to the file <filename>checkoutlist</filename> in that directory as well, and commit that change. This will cause a copy of &dhpackage; to be checked out into the repository itself. Copy te &dhpackage; script into the directory, make sure that it is executable by everyone (you should use <command>chmod a+x &dhpackage;</command> for this), and use the <command>cvs add</command> and <command>cvs commit</command> commands to add it to the repository. Once the commit is complete, a checked-out copy of the &dhpackage; script should be located in the repository in the <filename class="directory">CVSROOT</filename> directory in the repository. This is the usual way of integrating &dhpackage; into a CVS repository. </para> <para> To install &dhpackage; outside of the repository, find a location for the script. This can be in a "bin" directory such as <filename class="directory">/usr/local/bin/</filename>, or can be in some other location. The only requirement is that all users of the repository be able to execute the script (you should use <command>chmod a+x &dhpackage;</command> for this). This approach requires direct access to the CVS server machine, and is most useful if several repositories are going to share a single copy of &dhpackage; (maybe to ensure the same version is used for each; it's not large enough for disk space to be an issue). </para> </refsect2> <refsect2> <title>Configure CVS to use &dhpackage;</title> <para> Getting the CVS server to invoke &dhpackage; requires editing one more file in the <filename class="directory">CVSROOT</filename> module of the repository. Even if you're using a shared installation of &dhpackage;, this configuration needs to be performed for each repository. </para> <para> The <filename>commitinfo</filename> file in the <filename class="directory">CVSROOT</filename> module needs to be modified to invoke &dhpackage; when appropriate. Just when is appropriate depends entirely on your project. If your <filename>commitinfo</filename> file still contains the comments that <command>cvs init</command> copies in, this is a good time to read them if you haven't. If the file does not already contain any configuration lines, you can simply add to the end of the file. </para> <para> Here are some example lines to get you started: <literallayout> DEFAULT $CVSROOT/CVSROOT/branchctl ProjectOne $CVSROOT/CVSROOT/branchctl --no-config ProjectTwo $CVSROOT/CVSROOT/branchctl --config project-two.conf </literallayout> </para> <para> The first line causes the default configuration file, <filename>&dhpackage;.conf</filename>, to be used everywhere that doesn't use an alternate invocation of &dhpackage;. </para> <para> The second line tells CVS to use &dhpackage;'s internal configuration defaults instead of reading a configuration file, but to only do so in the the <filename class="directory">ProjectOne</filename> directory of the repository. </para> <para> The third line tells CVS to run &dhpackage; using a separate configuration file for the <filename class="directory">ProjectTwo</filename> directory in the repository. </para> <para> To finish the repository configuration, commit the changes you've made. Once the CVS server has reported that it is "Rebuilding administrative file database", your repository is configured to use &dhpackage;. </para> </refsect2> </refsect1> <refsect1> <title>Options</title> <para> When an option includes an argument, you may specify the argument either separate ("-d output") or mashed ("-doutput"). &dhpackage; supports both. For long options which include an argument, the argument may be separated from the option ("--fromhost example.com") or mashed, but with an equals sign between the option and the argument ("--fromhost=example.com"). </para> <variablelist> <varlistentry> <term><option>--config <replaceable>file</replaceable></option></term> <listitem> <para> Use <replaceable>file</replaceable> as the configuration file for &dhpackage;. By default, a file named <filename>&dhpackage;.conf</filename> is used if it exists. If the name of the configuration file is relative, it is interpreted as relative to the <filename class="directory">CVSROOT</filename> administrative directory of the repository. <option>--config</option> is incompatible with <option>--no-config</option>. </para> </listitem> </varlistentry> <varlistentry> <term><option>--no-config</option></term> <listitem> <para> Do not use a configuration file for &dhpackage;. This can be used to disable the use of the default configuration file. <option>--no-config</option> is incompatible with <option>--config</option>. Note that it's not normally useful to specify this option, but it may be useful when you want to allow changes to any branch within a single CVS module, but use a more sophisticated configuration for the rest of the repository. </para> </listitem> </varlistentry> <varlistentry> <term><option>--cvsroot <replaceable>path</replaceable></option></term> <listitem> <para> Use <replaceable>path</replaceable> as the value for the <envar>CVSROOT</envar> environment variable. This is usually not needed. </para> </listitem> </varlistentry> <varlistentry> <term><option>--help</option></term> <term><option>-h</option></term> <listitem> <para> Print a summary of the command line options to standard output. </para> </listitem> </varlistentry> </variablelist> </refsect1> <refsect1> <title>Bugs</title> <para> There are probably some bugs. If you find them, please report them to the maintainers using the <ulink url="http://sourceforge.net/projects/cvs-syncmail/">bug tracker</ulink>. </para> </refsect1> <refsect1> <title>See Also</title> <para> The <ulink url="http://sourceforge.net/projects/cvs-syncmail/" >&dhpackage; page</ulink> on &sourceforge;. </para> <para> The <ulink url="http://www.cvshome.org/">CVS home page</ulink>. </para> </refsect1> <refsect1> <title>Author</title> <para> &dhpackage; was originally written by Fred Drake. </para> <para> This manual page was written by &dhusername; &dhemail;. </para> </refsect1> </refentry> <!-- Keep this comment at the end of the file Local variables: mode: sgml sgml-omittag:t sgml-shorttag:t sgml-minimize-attributes:nil sgml-always-quote-attributes:t sgml-indent-step:2 sgml-indent-data:t sgml-parent-document:nil sgml-default-dtd-file:nil sgml-exposed-tags:nil sgml-local-catalogs:nil sgml-local-ecat-files:nil End: --> |
|
From: Fred L. D. <fd...@us...> - 2003-07-15 17:43:00
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv5197
Added Files:
Tag: new-config-branch
sample.conf
Removed Files:
Tag: new-config-branch
syncmail.conf
Log Message:
Rename syncmail.conf to sample.conf since it is only intended as a sample,
not as a template.
--- NEW FILE: sample.conf ---
; In values, substitutions for $BRANCH, $CVSROOT, and $HOSTNAME are
; available. These may also be spelled with curlies (for example:
; ${BRANCH}). These are replaced by the branch name (or the empty
; string for the trunk), the CVSROOT environment variable (not the
; root specified using --cvsroot), and the hostname (from the HOSTNAME
; environment variable or, if not set, the fully-qualified hostname).
[general]
; miscellaneous
verbose = true
email = true
; the kind of diff we generate
context-lines = 2
diff-type = unified
; how email is generated
from-host = $HOSTNAME
reply-to =
smtp-server = localhost
subject-prefix =
to = cvs...@li...
[branch]
; the * branch applies to all branches
subject-prefix = $BRANCH:
[branch my-project-branch]
email = false
[branch another-branch]
subject-prefix = [Special]
to = my...@ex...
--- syncmail.conf DELETED ---
|
|
From: Fred L. D. <fd...@us...> - 2003-07-15 16:13:53
|
Update of /cvsroot/cvs-syncmail/syncmail/doc
In directory sc8-pr-cvs1:/tmp/cvs-serv20085
Modified Files:
syncmail.sgml syncmail.1
Log Message:
Use normal case for section headings; stylesheets can transform if desired.
Index: syncmail.sgml
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/doc/syncmail.sgml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- syncmail.sgml 8 Jul 2003 21:20:23 -0000 1.3
+++ syncmail.sgml 15 Jul 2003 16:13:50 -0000 1.4
@@ -13,13 +13,13 @@
<!ENTITY dhfirstname "<firstname>Fred</firstname>">
<!ENTITY dhsurname "<surname>Drake</surname>">
<!-- Please adjust the date whenever revising the manpage. -->
- <!ENTITY dhdate "<date>July 8, 2003</date>">
+ <!ENTITY dhdate "<date>July 15, 2003</date>">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1). -->
<!ENTITY dhsection "<manvolnum>1</manvolnum>">
<!ENTITY dhemail "<email>fd...@ac...</email>">
<!ENTITY dhusername "Fred L. Drake, Jr.">
- <!ENTITY dhucpackage "<refentrytitle>SYNCMAIL</refentrytitle>">
+ <!ENTITY dhucpackage "<refentrytitle>syncmail</refentrytitle>">
<!ENTITY dhpackage "syncmail">
<!ENTITY debian "<productname>Debian GNU/Linux</productname>">
@@ -73,7 +73,7 @@
</refsynopsisdiv>
<refsect1>
- <title>DESCRIPTION</title>
+ <title>Description</title>
<para>
<command>&dhpackage;</command> sends out notifications of CVS
commits via email, including the patch that was applied for
@@ -109,7 +109,7 @@
</refsect1>
<refsect1>
- <title>SETTING UP SYNCMAIL</title>
+ <title>Setting Up syncmail</title>
<para>
Setting up &dhpackage; is not difficult, but there are usually
several steps:
@@ -266,7 +266,7 @@
</refsect1>
<refsect1>
- <title>OPTIONS</title>
+ <title>Options</title>
<para>
When an option includes an argument, you may specify the
argument either separate ("-d output") or mashed ("-doutput").
@@ -403,7 +403,7 @@
</refsect1>
<refsect1>
- <title>BUGS</title>
+ <title>Bugs</title>
<para>
There are probably some bugs. If you find them, please
report them to the maintainers using the <ulink
@@ -413,7 +413,7 @@
</refsect1>
<refsect1>
- <title>ALTERNATIVES</title>
+ <title>Alternatives</title>
<para>
Other people have written tools that serve similar purposes, but
not all of these are meant to support CVS repositories accessed
@@ -440,7 +440,7 @@
</refsect1>
<refsect1>
- <title>SEE ALSO</title>
+ <title>See Also</title>
<para>
The <ulink url="http://sourceforge.net/projects/cvs-syncmail/"
>&dhpackage; page</ulink> on &sourceforge;.
@@ -452,7 +452,7 @@
</refsect1>
<refsect1>
- <title>AUTHOR</title>
+ <title>Author</title>
<para>
&dhpackage; was originally written by Barry Warsaw to send mail
based on checkins to the Python project. Barry continues to
Index: syncmail.1
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/doc/syncmail.1,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- syncmail.1 8 Jul 2003 21:20:23 -0000 1.3
+++ syncmail.1 15 Jul 2003 16:13:50 -0000 1.4
@@ -3,7 +3,7 @@
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <st...@gg...>.
-.TH "SYNCMAIL" "1" "08 July 2003" "" ""
+.TH "SYNCMAIL" "1" "15 July 2003" "" ""
.SH NAME
syncmail \- Send email notifications of CVS activity
|
|
From: Fred L. D. <fd...@us...> - 2003-07-14 18:23:23
|
Update of /cvsroot/cvs-syncmail/syncmail/doc
In directory sc8-pr-cvs1:/tmp/cvs-serv360
Modified Files:
Tag: new-config-branch
syncmail.sgml
Log Message:
Remove the "required" indicators from positional command-line
arguments; nothing is absolutely required if the config file provides
enough information.
Index: syncmail.sgml
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/doc/syncmail.sgml,v
retrieving revision 1.3.2.1
retrieving revision 1.3.2.2
diff -u -d -r1.3.2.1 -r1.3.2.2
--- syncmail.sgml 10 Jul 2003 14:08:24 -0000 1.3.2.1
+++ syncmail.sgml 14 Jul 2003 18:23:17 -0000 1.3.2.2
@@ -69,8 +69,8 @@
<arg>--subject-prefix <replaceable>string</replaceable></arg>
<arg>-S <replaceable>string</replaceable></arg>
<arg><option>--help</option> | <option>-h</option></arg>
- <arg choice="req">%{sSv}</arg>
- <arg choice="req" rep="repeat">email</arg>
+ <arg>%{sSv}</arg>
+ <arg rep="repeat">email</arg>
</cmdsynopsis>
</refsynopsisdiv>
|
|
From: Fred L. D. <fd...@us...> - 2003-07-14 18:12:53
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv28157
Modified Files:
Tag: new-config-branch
syncmail
Log Message:
- update commented-out code
Index: syncmail
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/syncmail,v
retrieving revision 1.36.2.17
retrieving revision 1.36.2.18
diff -u -d -r1.36.2.17 -r1.36.2.18
--- syncmail 14 Jul 2003 17:01:32 -0000 1.36.2.17
+++ syncmail 14 Jul 2003 18:12:50 -0000 1.36.2.18
@@ -371,7 +371,7 @@
## name = string.split(line, "/")[1]
## dirname = namekey(prefix, name)
## if os.path.isdir(dirname):
-## m = load_change_info(dirname)
+## m = load_entries(dirname)
## mapping.update(m)
if line[0] == "/":
# normal file
|
|
From: Fred L. D. <fd...@us...> - 2003-07-14 18:11:51
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv28022
Modified Files:
branchctl
Log Message:
- update commented-out code
- remove function that isn't used in this script
Index: branchctl
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/branchctl,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- branchctl 14 Jul 2003 16:49:30 -0000 1.2
+++ branchctl 14 Jul 2003 18:11:47 -0000 1.3
@@ -141,42 +141,13 @@
## name = string.split(line, "/")[1]
## dirname = namekey(prefix, name)
## if os.path.isdir(dirname):
-## m = load_change_info(dirname)
+## m = load_entries(dirname)
## mapping.update(m)
if line[0] == "/":
# normal file
get_entry(prefix, mapping, line, entries_fn)
# else: bogus Entries line
f.close()
- return mapping
-
-def load_change_info(mapping, prefix=None):
- if prefix is not None:
- entries_log_fn = os.path.join(prefix, "CVS", "Entries.Log")
- else:
- entries_log_fn = os.path.join("CVS", "Entries.Log")
- if os.path.isfile(entries_log_fn):
- f = open(entries_log_fn)
- while 1:
- line = f.readline()
- if not line:
- break
- if line[1:2] != ' ':
- # really old version of CVS
- break
- entry = get_entry(prefix, mapping, line[2:], entries_log_fn)
- parts = string.split(line, "/")[1:]
- if line[0] == "A":
- # adding a file
- entry.new_revision = parts[1]
- elif line[0] == "R":
- # removing a file
- entry.new_revision = None
- f.close()
- for entry in mapping.values():
- if not hasattr(entry, "new_revision"):
- print 'confused about file', entry.name, '-- ignoring'
- del mapping[entry.name]
return mapping
def load_branch_name():
|
|
From: Fred L. D. <fd...@us...> - 2003-07-14 17:01:36
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv14964
Modified Files:
Tag: new-config-branch
syncmail
Log Message:
Merge in many changes and refactorings based on the development of branchctl.
Index: syncmail
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/syncmail,v
retrieving revision 1.36.2.16
retrieving revision 1.36.2.17
diff -u -d -r1.36.2.16 -r1.36.2.17
--- syncmail 11 Jul 2003 18:47:35 -0000 1.36.2.16
+++ syncmail 14 Jul 2003 17:01:32 -0000 1.36.2.17
@@ -39,7 +39,7 @@
--config=file
Use file as the configuration file. By default, a file named
- syncmail.conf is used if it exists. If the name of the
+ %(DEFAULT_CONFIGURATION_FILE)s is used if it exists. If the name of the
configuration file is relative, it is interpreted as relative
to the CVSROOT administrative directory of the repository.
--config is incompatible with --no-config.
@@ -131,9 +131,21 @@
fqdn = 'localhost.localdomain'
return fqdn
-
from cStringIO import StringIO
+DEFAULT_CONFIGURATION_FILE = "syncmail.conf"
+
+DEFAULT_CONFIGURATION = {
+ "context-lines": "2",
+ "diff-type": "unified",
+ "email": "true",
+ "from-host": "$HOSTNAME",
+ "smtp-server": "localhost",
+ "smtp-server": "localhost",
+ "subject-prefix": "",
+ "verbose": "true",
+ }
+
# Which SMTP server to do we connect to?
MAILHOST = 'localhost'
MAILPORT = 25
@@ -315,6 +327,9 @@
parts = string.split(line, "/")
_, name, revision, timestamp, options, tagdate = parts
tagdate = string.rstrip(tagdate) or None
+ if tagdate:
+ assert tagdate[0] == "T"
+ tagdate = tagdate[1:]
key = namekey(prefix, name)
try:
entry = mapping[key]
@@ -336,12 +351,11 @@
else:
return name
-def load_change_info(prefix=None):
+def load_entries(prefix=None):
if prefix is not None:
entries_fn = os.path.join(prefix, "CVS", "Entries")
else:
entries_fn = os.path.join("CVS", "Entries")
- entries_log_fn = entries_fn + ".Log"
mapping = {}
f = open(entries_fn)
while 1:
@@ -364,6 +378,13 @@
get_entry(prefix, mapping, line, entries_fn)
# else: bogus Entries line
f.close()
+ return mapping
+
+def load_change_info(mapping, prefix=None):
+ if prefix is not None:
+ entries_log_fn = os.path.join(prefix, "CVS", "Entries.Log")
+ else:
+ entries_log_fn = os.path.join("CVS", "Entries.Log")
if os.path.isfile(entries_log_fn):
f = open(entries_log_fn)
while 1:
@@ -502,35 +523,23 @@
class ConfigurationDatabase:
- # The defaults set covers what we need but might not get from the
- # command line or configuration file.
- defaults = {
- "context-lines": "2",
- "diff-type": "unified",
- "email": "true",
- "from-host": "$HOSTNAME",
- "smtp-server": "localhost",
- "smtp-server": "localhost",
- "subject-prefix": "",
- "verbose": "true",
- }
-
def __init__(self, filename, cmdline, args):
self.args = args
self.cmdline = cmdline
self.config = None
if filename and os.path.isfile(filename):
self.config = ConfigParser()
- if hasattr(cp, "readfp"):
+ if hasattr(self.config, "readfp"):
self.config.readfp(open(filename), filename)
else:
# We have to use this old method for compatibility with
# ancient versions of Python.
self.config.read([filename])
- def get_config(self, branch):
+ def get_config(self, branch=None):
dicts = []
if self.config:
+ cp = self.config
if branch:
dicts.append(get_section_as_dict(cp, "branch " + branch))
dicts.append(get_section_as_dict(cp, "branch"))
@@ -539,9 +548,71 @@
else:
dicts.append(self.cmdline)
dicts = filter(None, dicts)
- dicts.append(self.defaults)
+ dicts.append(DEFAULT_CONFIGURATION)
return Options(OptionLookup(dicts, branch), self.args)
+class OptionsBase:
+
+ def __init__(self, config, args):
+ self.args = args
+ self.verbose = config.getbool('verbose')
+ fn = os.path.join("CVS", "Repository")
+ if os.path.isfile(fn):
+ f = open(fn)
+ self.repodir = string.strip(f.readline())
+ f.close()
+ else:
+ self.repodir = os.curdir
+
+
+def get_admin_file(name):
+ if os.environ.has_key("CVSROOT"):
+ p = os.path.join(os.environ["CVSROOT"], "CVSROOT", name)
+ return os.path.abspath(p)
+ else:
+ return os.path.join("CVSROOT", name)
+
+def load_configuration(args, branch=None):
+ cmdline, args = load_cmdline(args)
+ defconfig = get_admin_file(DEFAULT_CONFIGURATION_FILE)
+ if cmdline.has_key('config-file'):
+ cfgfile = get_admin_file(cmdline['config-file'])
+ del cmdline['config-file']
+ elif os.path.isfile(defconfig):
+ cfgfile = defconfig
+ else:
+ cfgfile = None
+ return ConfigurationDatabase(cfgfile, cmdline, args)
+
+
+class Options(OptionsBase):
+
+ def __init__(self, config, args):
+ OptionsBase.__init__(self, config, args)
+
+ self.contextlines = config.getint('context-lines')
+ self.diff_type = config.get('diff-type')
+ if self.diff_type not in ('context', 'unified'):
+ usage(1, "invalid diff-type specified in configuration file")
+ self.subject_prefix = config.get('subject-prefix')
+ self.replyto = config.get('reply-to')
+ self.fromhost = config.get('from-host')
+ self.email = config.getbool('email')
+ address = config.getaddress('smtp-server')
+ self.smtp_server, self.smtp_port = address
+ if args:
+ self.cvsinfo = args[0]
+ self.subject = self.subject_prefix + " " + self.cvsinfo
+ else:
+ self.cvsinfo = ""
+ self.subject = self.subject_prefix + " changes"
+ # The remaining args should be the email addresses
+ if len(args) >= 2:
+ self.people = string.join(args[1:], COMMASPACE)
+ else:
+ self.people = config.get("to")
+
+
def load_cmdline(args):
try:
opts, args = getopt.getopt(args,
@@ -584,64 +655,11 @@
set('smtp-server', arg)
return cmdline, args
-class Options:
- def __init__(self, config, args):
- self.contextlines = config.getint('context-lines')
- self.diff_type = config.get('diff-type')
- if self.diff_type not in ('context', 'unified'):
- usage(1, "invalid diff-type specified in configuration file")
- self.verbose = config.getbool('verbose')
- self.subject_prefix = config.get('subject-prefix')
- self.replyto = config.get('reply-to')
- self.fromhost = config.get('from-host')
- self.email = config.getbool('email')
- address = config.getaddress('smtp-server')
- self.smtp_server, self.smtp_port = address
- self.args = args
- if args:
- self.cvsinfo = args[0]
- self.subject = self.subject_prefix + " " + self.cvsinfo
- else:
- self.cvsinfo = ""
- self.subject = self.subject_prefix + " changes"
- # The remaining args should be the email addresses
- if len(args) >= 2:
- self.people = string.join(args[1:], COMMASPACE)
- else:
- self.people = config.get("to")
-
- fn = os.path.join("CVS", "Repository")
- if os.path.isfile(fn):
- f = open(fn)
- self.repodir = string.strip(f.readline())
- f.close()
- else:
- self.repodir = os.curdir
-
-def get_admin_file(name):
- if os.environ.has_key("CVSROOT"):
- p = os.path.join(os.environ["CVSROOT"], "CVSROOT", name)
- return os.path.abspath(p)
- else:
- return os.path.join("CVSROOT", name)
-def load_configuration(args, branch=None):
- cmdline, args = load_cmdline(args)
- defconfig = get_admin_file("syncmail.conf")
- if cmdline.has_key('config-file'):
- cfgfile = get_admin_file(cmdline['config-file'])
- del cmdline['config-file']
- elif os.path.isfile(defconfig):
- cfgfile = defconfig
- else:
- cfgfile = None
- db = ConfigurationDatabase(cfgfile, cmdline, args)
- return db.get_config(branch)
-
-
def main():
# load the options
- config = load_configuration(sys.argv[1:], load_branch_name())
+ db = load_configuration(sys.argv[1:])
+ config = db.get_config(load_branch_name())
if not config.people:
# Nobody to send mail to!
@@ -660,7 +678,7 @@
print 'Not sending email for imported sources.'
return
- items = load_change_info().items()
+ items = load_change_info(load_entries()).items()
items.sort()
changes = []
for name, entry in items:
|
|
From: Fred L. D. <fd...@us...> - 2003-07-14 17:01:36
|
Update of /cvsroot/cvs-syncmail/syncmail/tests
In directory sc8-pr-cvs1:/tmp/cvs-serv14964/tests
Modified Files:
Tag: new-config-branch
test_options.py
Log Message:
Merge in many changes and refactorings based on the development of branchctl.
Index: test_options.py
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/tests/Attic/test_options.py,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -u -d -r1.1.2.4 -r1.1.2.5
--- test_options.py 11 Jul 2003 12:27:18 -0000 1.1.2.4
+++ test_options.py 14 Jul 2003 17:01:32 -0000 1.1.2.5
@@ -73,7 +73,7 @@
self.assertEqual(args, [])
def test_load_configuration_empty(self):
- config = syncmail.load_configuration([])
+ config = syncmail.load_configuration([]).get_config()
self.assertEqual(config.contextlines, 2)
self.assertEqual(config.verbose, 1)
self.assertEqual(config.smtp_server, syncmail.MAILHOST)
@@ -81,18 +81,18 @@
def test_load_configuration_simple(self):
config = syncmail.load_configuration(
- ['-q', '--mailhost=smtp.example.com'])
+ ['-q', '--mailhost=smtp.example.com']).get_config()
self.assertEqual(config.verbose, 0)
self.assertEqual(config.smtp_server, "smtp.example.com")
self.assertEqual(config.smtp_port, syncmail.MAILPORT)
def test_load_configuration_smtp_address(self):
config = syncmail.load_configuration(
- ['--mailhost=smtp.example.com:8025'])
+ ['--mailhost=smtp.example.com:8025']).get_config()
self.assertEqual(config.smtp_server, "smtp.example.com")
self.assertEqual(config.smtp_port, 8025)
- config = syncmail.load_configuration(['--mailhost=:8025'])
+ config = syncmail.load_configuration(['--mailhost=:8025']).get_config()
self.assertEqual(config.smtp_server, syncmail.MAILHOST)
self.assertEqual(config.smtp_port, 8025)
|
|
From: Fred L. D. Jr. <fd...@ac...> - 2003-07-14 16:52:03
|
I've just added a new script to the cvs-syncmail CVS trunk: branchctl.
This script controls the use of branches within a CVS repository.
For each branch (including the trunk), two controls are available:
- whether the branch is open for commits, and
- whether commits involving that branch and any other should be
permitted.
Both default to true since that's the normal CVS behavior.
Much of this code is based on the new-config-branch version of
syncmail, and allowed portions of that to be tested in a simpler
environment.
The configuration file should be present in the CSVROOT administrative
directory alongside the script. The configuration files have the same
structure as the strawman configuration file for syncmail, but
different keys are checked:
open
Indicates whether checkins are allowed. The value may be "true"
or "false"; the default is "true".
cross-branch-commits
Indicates whether a single commit may span multiple branches. The
implementation only checks this for a single directory at a time;
commits that affect one branch in one directory and another branch
in a separate directory are not (yet) detected. The value may be
"true" or "false"; the default is "true".
An example configuration may look like this:
----------------------------------------
[general]
open = true
cross-branch-commits = false
[branch unmaintained-maintenance-branch]
; we don't like this branch any more
open = false
----------------------------------------
This configuration data can co-exist in the configuration file for the
new version of syncmail that's currently in development, so all your
branch-control configuration can be in one place. The default
configuration file names are different for the two scripts; I'll
suggest appropriate usage would be to create a single file and name it
explicitly using the --config option for each script.
This script may provide a good foundation for additional forms of
access control for CVS repositories as well.
-Fred
--
Fred L. Drake, Jr. <fdrake at acm.org>
PythonLabs at Zope Corporation
|
|
From: Fred L. D. <fd...@us...> - 2003-07-14 16:49:44
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv11396
Modified Files:
branchctl
Log Message:
This time, actually copy in the tested, working version of the script
from my test repository.
Index: branchctl
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/branchctl,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- branchctl 14 Jul 2003 16:30:00 -0000 1.1
+++ branchctl 14 Jul 2003 16:49:30 -0000 1.2
@@ -16,7 +16,7 @@
--config=file
Use file as the configuration file. By default, a file named
- %(DEFAULT_CONFIGURATION_FILE) is used if it exists. If the name of the
+ %(DEFAULT_CONFIGURATION_FILE)s is used if it exists. If the name of the
configuration file is relative, it is interpreted as relative
to the CVSROOT administrative directory of the repository.
--config is incompatible with --no-config.
@@ -43,14 +43,34 @@
import getopt
import os
import re
+import socket
import string
import sys
+try:
+ from socket import getfqdn
+except ImportError:
+ def getfqdn():
+ # Python 1.5.2 :(
+ hostname = socket.gethostname()
+ byaddr = socket.gethostbyaddr(socket.gethostbyname(hostname))
+ aliases = byaddr[1]
+ aliases.insert(0, byaddr[0])
+ aliases.insert(0, hostname)
+ for fqdn in aliases:
+ if '.' in fqdn:
+ break
+ else:
+ fqdn = 'localhost.localdomain'
+ return fqdn
+
+
DEFAULT_CONFIGURATION_FILE = "branchctl.conf"
DEFAULT_CONFIGURATION = {
"verbose": "true",
"open": "true",
+ "cross-branch-commits": "true",
}
@@ -77,6 +97,9 @@
parts = string.split(line, "/")
_, name, revision, timestamp, options, tagdate = parts
tagdate = string.rstrip(tagdate) or None
+ if tagdate:
+ assert tagdate[0] == "T"
+ tagdate = tagdate[1:]
key = namekey(prefix, name)
try:
entry = mapping[key]
@@ -98,12 +121,11 @@
else:
return name
-def load_change_info(prefix=None):
+def load_entries(prefix=None):
if prefix is not None:
entries_fn = os.path.join(prefix, "CVS", "Entries")
else:
entries_fn = os.path.join("CVS", "Entries")
- entries_log_fn = entries_fn + ".Log"
mapping = {}
f = open(entries_fn)
while 1:
@@ -126,6 +148,13 @@
get_entry(prefix, mapping, line, entries_fn)
# else: bogus Entries line
f.close()
+ return mapping
+
+def load_change_info(mapping, prefix=None):
+ if prefix is not None:
+ entries_log_fn = os.path.join(prefix, "CVS", "Entries.Log")
+ else:
+ entries_log_fn = os.path.join("CVS", "Entries.Log")
if os.path.isfile(entries_log_fn):
f = open(entries_log_fn)
while 1:
@@ -270,7 +299,7 @@
self.config = None
if filename and os.path.isfile(filename):
self.config = ConfigParser()
- if hasattr(cp, "readfp"):
+ if hasattr(self.config, "readfp"):
self.config.readfp(open(filename), filename)
else:
# We have to use this old method for compatibility with
@@ -280,6 +309,7 @@
def get_config(self, branch):
dicts = []
if self.config:
+ cp = self.config
if branch:
dicts.append(get_section_as_dict(cp, "branch " + branch))
dicts.append(get_section_as_dict(cp, "branch"))
@@ -288,7 +318,7 @@
else:
dicts.append(self.cmdline)
dicts = filter(None, dicts)
- dicts.append(DEFAULT_CONFIGURATION.copy())
+ dicts.append(DEFAULT_CONFIGURATION)
return Options(OptionLookup(dicts, branch), self.args)
@@ -334,7 +364,7 @@
OptionsBase.__init__(self, config, args)
self.open = config.getbool("open")
-
+ self.cross_commits = config.getbool("cross-branch-commits")
def load_cmdline(args):
try:
@@ -364,23 +394,36 @@
def main():
branch = load_branch_name()
- configdb = load_configuration(sys.argv[1:], branch)
- changes = load_change_info().values()
+ configdb = load_configuration(sys.argv[1:])
+ changes = load_entries().values()
d = {}
for change in changes:
- tag = changes.tagdate or branch
- d[tag] = 1
- closed = 0
+ tag = change.tagdate or branch
+ if d.has_key(tag):
+ d[tag].append(change)
+ else:
+ d[tag] = [change]
+ denied = 0
+ crossed_branches = len(d) > 1
for tag in d.keys():
config = configdb.get_config(tag)
+ if tag:
+ branchname = "branch " + tag
+ else:
+ branchname = "trunk"
if not config.open:
- closed = 1
- if tag:
- print "branch %s is closed" % `tag`
- else:
- print "trunk is closed"
- if closed:
+ if not denied:
+ denied = 1
+ print
+ print branchname, "is closed"
+ if crossed_branches and not config.cross_commits:
+ if not denied:
+ denied = 1
+ print
+ print branchname, "does not permit cross-branch commits"
+ if denied:
+ print
sys.exit(1)
|
|
From: Fred L. D. <fd...@us...> - 2003-07-14 16:30:04
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv7352
Added Files:
branchctl
Log Message:
Script which controls the use of branches within a CVS repository.
For each branch (including the trunk), two controls are available:
whether the branch is open for commits, and whether commits involving
that branch and any other should be permitted. Both default to true
since that's the normal CVS behavior.
Much of this code is based on the new-config-branch version of
syncmail, and allowed portions of that to be tested in a simpler
environment.
--- NEW FILE: branchctl ---
#! /usr/bin/env python
#
# Script to control whether CVS branches are open or closed for
# changes.
#
# This is intended to be called from the commitinfo hook.
"""\
Script which controls the use of branches within a CVS repository.
Usage:
%(PROGRAM)s [options] [<%%S> [email-addr ...]]
Where options are:
--config=file
Use file as the configuration file. By default, a file named
%(DEFAULT_CONFIGURATION_FILE) is used if it exists. If the name of the
configuration file is relative, it is interpreted as relative
to the CVSROOT administrative directory of the repository.
--config is incompatible with --no-config.
--no-config
Do not use a configuration file. This can be used to disable
the use of the default configuration file. --no-config is
incompatible with --config.
--cvsroot=<path>
Use <path> as the environment variable CVSROOT. Otherwise this
variable must exist in the environment.
--quiet / -q
Don't print as much status to stdout.
--help / -h
Print this text.
"""
# The configuration data can co-exist in the same configuration file
# with the configuration for the "new-world" version of syncmail.
import getopt
import os
import re
import string
import sys
DEFAULT_CONFIGURATION_FILE = "branchctl.conf"
DEFAULT_CONFIGURATION = {
"verbose": "true",
"open": "true",
}
def usage(code, msg=''):
print __doc__ % globals()
if msg:
print msg
sys.exit(code)
class CVSEntry:
def __init__(self, name, revision, timestamp, conflict, options, tagdate):
self.name = name
self.revision = revision
self.timestamp = timestamp
self.conflict = conflict
self.options = options
self.tagdate = tagdate
def get_entry(prefix, mapping, line, filename):
line = string.strip(line)
parts = string.split(line, "/")
_, name, revision, timestamp, options, tagdate = parts
tagdate = string.rstrip(tagdate) or None
key = namekey(prefix, name)
try:
entry = mapping[key]
except KeyError:
if revision == "0":
revision = None
if "+" in timestamp:
timestamp, conflict = tuple(string.split(timestamp, "+"))
else:
conflict = None
entry = CVSEntry(key, revision, timestamp, conflict,
options, tagdate)
mapping[key] = entry
return entry
def namekey(prefix, name):
if prefix:
return os.path.join(prefix, name)
else:
return name
def load_change_info(prefix=None):
if prefix is not None:
entries_fn = os.path.join(prefix, "CVS", "Entries")
else:
entries_fn = os.path.join("CVS", "Entries")
entries_log_fn = entries_fn + ".Log"
mapping = {}
f = open(entries_fn)
while 1:
line = f.readline()
if not line:
break
## if string.strip(line) == "D":
## continue
# we could recurse down subdirs, except the Entries.Log files
# we need haven't been written to the subdirs yet, so it
# doesn't do us any good
## if line[0] == "D":
## name = string.split(line, "/")[1]
## dirname = namekey(prefix, name)
## if os.path.isdir(dirname):
## m = load_change_info(dirname)
## mapping.update(m)
if line[0] == "/":
# normal file
get_entry(prefix, mapping, line, entries_fn)
# else: bogus Entries line
f.close()
if os.path.isfile(entries_log_fn):
f = open(entries_log_fn)
while 1:
line = f.readline()
if not line:
break
if line[1:2] != ' ':
# really old version of CVS
break
entry = get_entry(prefix, mapping, line[2:], entries_log_fn)
parts = string.split(line, "/")[1:]
if line[0] == "A":
# adding a file
entry.new_revision = parts[1]
elif line[0] == "R":
# removing a file
entry.new_revision = None
f.close()
for entry in mapping.values():
if not hasattr(entry, "new_revision"):
print 'confused about file', entry.name, '-- ignoring'
del mapping[entry.name]
return mapping
def load_branch_name():
tag_fn = os.path.join("CVS", "Tag")
if os.path.isfile(tag_fn):
f = open(tag_fn)
line = string.strip(f.readline())
f.close()
if line[:1] == "T":
return line[1:]
return None
TRUE_VALUES = ('true', 'on', 'enabled')
FALSE_VALUES = ('false', 'off', 'disabled')
class OptionLookup:
def __init__(self, dicts, branch=None):
self._dicts = dicts
self._replace = Replacer({
"BRANCH": branch or "",
"CVSROOT": os.environ.get("CVSROOT", ""),
"HOSTNAME": os.environ.get("HOSTNAME") or getfqdn(),
})
def get(self, option):
for dict in self._dicts:
v = dict.get(option)
if v is not None:
return self._replace(v)
return None
def getbool(self, option):
v = self.get(option)
if v is not None:
v = string.lower(v)
if v in TRUE_VALUES:
v = 1
elif v in FALSE_VALUES:
v = 0
else:
raise ValueError("illegal boolean value: %s" % `v`)
return v
def getint(self, option):
v = self.get(option)
if v is not None:
v = int(v)
return v
def getaddress(self, option):
"""Return (host, port) for a host:port or host string.
The port, if ommitted, will be None.
"""
v = self.get(option)
if v is None:
return MAILHOST, MAILPORT
elif ":" in v:
h, p = tuple(string.split(v, ":"))
p = int(p)
return h or MAILHOST, p
else:
return v, MAILPORT
# Support for $VARIABLE replacement.
class Replacer:
def __init__(self, vars):
self._vars = vars
rx = re.compile(r"\$([a-zA-Z][a-zA-Z_]*\b|\{[a-zA-Z][a-zA-Z_]*\})")
self._search = rx.search
def __call__(self, v):
v, name, suffix = self._split(v)
while name:
v = v + self._vars.get(name, "")
prefix, name, suffix = self._split(suffix)
v = v + prefix
return v
def _split(self, s):
m = self._search(s)
if m is not None:
name = m.group(1)
if name[0] == "{":
name = name[1:-1]
return s[:m.start()], name, s[m.end():]
else:
return s, None, ''
def get_section_as_dict(config, section):
d = {}
if config.has_section(section):
for opt in config.options(section):
d[opt] = config.get(section, opt, raw=1)
return d
from ConfigParser import ConfigParser
class ConfigParser(ConfigParser):
# Regular expressions for parsing section headers and options,
# from the Python 2.3 version of ConfigParser.
SECTCRE = re.compile(
r'\[' # [
r'(?P<header>[^]]+)' # very permissive!
r'\]' # ]
)
# For compatibility with older versions:
__SECTCRE = SECTCRE
class ConfigurationDatabase:
def __init__(self, filename, cmdline, args):
self.args = args
self.cmdline = cmdline
self.config = None
if filename and os.path.isfile(filename):
self.config = ConfigParser()
if hasattr(cp, "readfp"):
self.config.readfp(open(filename), filename)
else:
# We have to use this old method for compatibility with
# ancient versions of Python.
self.config.read([filename])
def get_config(self, branch):
dicts = []
if self.config:
if branch:
dicts.append(get_section_as_dict(cp, "branch " + branch))
dicts.append(get_section_as_dict(cp, "branch"))
dicts.append(self.cmdline)
dicts.append(get_section_as_dict(cp, "general"))
else:
dicts.append(self.cmdline)
dicts = filter(None, dicts)
dicts.append(DEFAULT_CONFIGURATION.copy())
return Options(OptionLookup(dicts, branch), self.args)
class OptionsBase:
def __init__(self, config, args):
self.args = args
self.verbose = config.getbool('verbose')
fn = os.path.join("CVS", "Repository")
if os.path.isfile(fn):
f = open(fn)
self.repodir = string.strip(f.readline())
f.close()
else:
self.repodir = os.curdir
def get_admin_file(name):
if os.environ.has_key("CVSROOT"):
p = os.path.join(os.environ["CVSROOT"], "CVSROOT", name)
return os.path.abspath(p)
else:
return os.path.join("CVSROOT", name)
def load_configuration(args):
cmdline, args = load_cmdline(args)
if cmdline.has_key('config-file'):
cfgfile = get_admin_file(cmdline['config-file'])
del cmdline['config-file']
else:
defconfig = get_admin_file(DEFAULT_CONFIGURATION_FILE)
if os.path.isfile(defconfig):
cfgfile = defconfig
else:
cfgfile = None
return ConfigurationDatabase(cfgfile, cmdline, args)
class Options(OptionsBase):
def __init__(self, config, args):
OptionsBase.__init__(self, config, args)
self.open = config.getbool("open")
def load_cmdline(args):
try:
opts, args = getopt.getopt(args, 'hq',
['cvsroot=', 'config=', 'no-config',
'help', 'quiet'])
except getopt.error, msg:
usage(2, msg)
cmdline = {}
def set(option, value, cmdline=cmdline):
if cmdline.has_key(option):
usage(2, "can't set option more than once")
cmdline[option] = value
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
elif opt == '--cvsroot':
os.environ["CVSROOT"] = arg
elif opt == "--config":
set('config-file', arg)
elif opt == '--no-config':
set('config-file', '')
elif opt in ('-q', '--quiet'):
set('verbose', 'false')
return cmdline, args
def main():
branch = load_branch_name()
configdb = load_configuration(sys.argv[1:], branch)
changes = load_change_info().values()
d = {}
for change in changes:
tag = changes.tagdate or branch
d[tag] = 1
closed = 0
for tag in d.keys():
config = configdb.get_config(tag)
if not config.open:
closed = 1
if tag:
print "branch %s is closed" % `tag`
else:
print "trunk is closed"
if closed:
sys.exit(1)
if __name__ == '__main__':
main()
|
|
From: Fred L. D. Jr. <fd...@ac...> - 2003-07-11 19:50:24
|
Marc Wilson writes: > Is it possible to set up syncmail so that it only sends mails for > commits done in the HEAD branch, and not for other branches in the > repository? > > This is probably more of a loginfo question which I will chase up in the > CVS docs, but I was hoping someone here might know. I think this will be possible with a complete re-construction of syncmail that I have in progress. The "new syncmail" will use a configuration file that allows settings for each branch. I posted a strawman sample configuration file to the list earlier this week: http://sourceforge.net/mailarchive/forum.php?thread_id=2742501&forum_id=8207 Please take a look at that and let me know whether it meets your requirements. I'll be glad to answer questions as well. Development is underway, but there's still plenty of space for changes. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation |
|
From: Fred L. D. <fd...@us...> - 2003-07-11 18:47:38
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv717
Modified Files:
Tag: new-config-branch
syncmail
Log Message:
- clean up code to look for files in the CVSROOT directory
- look for config files named on the command line in the CVSROOT
directory
- remove XXX comment that is addressed by these changes
Index: syncmail
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/syncmail,v
retrieving revision 1.36.2.15
retrieving revision 1.36.2.16
diff -u -d -r1.36.2.15 -r1.36.2.16
--- syncmail 11 Jul 2003 18:39:03 -0000 1.36.2.15
+++ syncmail 11 Jul 2003 18:47:35 -0000 1.36.2.16
@@ -618,24 +618,23 @@
else:
self.repodir = os.curdir
-def load_configuration(args, branch=None):
- cmdline, args = load_cmdline(args)
+def get_admin_file(name):
if os.environ.has_key("CVSROOT"):
- defconfig = os.path.join(os.environ["CVSROOT"],
- "CVSROOT", "syncmail.conf")
+ p = os.path.join(os.environ["CVSROOT"], "CVSROOT", name)
+ return os.path.abspath(p)
else:
- defconfig = os.path.join("CVSROOT", "syncmail.conf")
+ return os.path.join("CVSROOT", name)
+
+def load_configuration(args, branch=None):
+ cmdline, args = load_cmdline(args)
+ defconfig = get_admin_file("syncmail.conf")
if cmdline.has_key('config-file'):
- cfgfile = cmdline['config-file']
+ cfgfile = get_admin_file(cmdline['config-file'])
del cmdline['config-file']
elif os.path.isfile(defconfig):
cfgfile = defconfig
else:
cfgfile = None
- # XXX cfgfile is specified relative to the CVSROOT directory; we
- # need to transform the path appropriately, since that won't be
- # the current directory when we try to read it. In fact, a wrong
- # config file may exist at the alternate location.
db = ConfigurationDatabase(cfgfile, cmdline, args)
return db.get_config(branch)
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 18:39:06
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv32120
Modified Files:
Tag: new-config-branch
syncmail
Log Message:
refactor to make it easier to get the configuration data for separate
branches without re-loading the configuration file
Index: syncmail
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/syncmail,v
retrieving revision 1.36.2.14
retrieving revision 1.36.2.15
diff -u -d -r1.36.2.14 -r1.36.2.15
--- syncmail 11 Jul 2003 17:51:33 -0000 1.36.2.14
+++ syncmail 11 Jul 2003 18:39:03 -0000 1.36.2.15
@@ -484,38 +484,28 @@
d[opt] = config.get(section, opt, raw=1)
return d
-def load_configfile(filename, cmdline, branch):
- dicts = []
- if filename:
- from ConfigParser import ConfigParser
- class ConfigParser(ConfigParser):
- # Regular expressions for parsing section headers and options,
- # from the Python 2.3 version of ConfigParser.
- SECTCRE = re.compile(
- r'\[' # [
- r'(?P<header>[^]]+)' # very permissive!
- r'\]' # ]
- )
- # For compatibility with older versions:
- __SECTCRE = SECTCRE
-
- cp = ConfigParser()
- # We have to use this old method for compatibility with
- # ancient versions of Python.
- cp.read([filename])
- if branch:
- dicts.append(get_section_as_dict(cp, "branch " + branch))
- dicts.append(get_section_as_dict(cp, "branch"))
- dicts.append(cmdline)
- dicts.append(get_section_as_dict(cp, "general"))
- else:
- dicts.append(cmdline)
- dicts = filter(None, dicts)
+from ConfigParser import ConfigParser
+class ConfigParser(ConfigParser):
+
+ # Regular expressions for parsing section headers and options,
+ # from the Python 2.3 version of ConfigParser.
+
+ SECTCRE = re.compile(
+ r'\[' # [
+ r'(?P<header>[^]]+)' # very permissive!
+ r'\]' # ]
+ )
+
+ # For compatibility with older versions:
+ __SECTCRE = SECTCRE
+
+
+class ConfigurationDatabase:
+
# The defaults set covers what we need but might not get from the
# command line or configuration file.
defaults = {
"context-lines": "2",
- "cvsroot": "$CVSROOT",
"diff-type": "unified",
"email": "true",
"from-host": "$HOSTNAME",
@@ -524,8 +514,33 @@
"subject-prefix": "",
"verbose": "true",
}
- dicts.append(defaults)
- return OptionLookup(dicts, branch)
+
+ def __init__(self, filename, cmdline, args):
+ self.args = args
+ self.cmdline = cmdline
+ self.config = None
+ if filename and os.path.isfile(filename):
+ self.config = ConfigParser()
+ if hasattr(cp, "readfp"):
+ self.config.readfp(open(filename), filename)
+ else:
+ # We have to use this old method for compatibility with
+ # ancient versions of Python.
+ self.config.read([filename])
+
+ def get_config(self, branch):
+ dicts = []
+ if self.config:
+ if branch:
+ dicts.append(get_section_as_dict(cp, "branch " + branch))
+ dicts.append(get_section_as_dict(cp, "branch"))
+ dicts.append(self.cmdline)
+ dicts.append(get_section_as_dict(cp, "general"))
+ else:
+ dicts.append(self.cmdline)
+ dicts = filter(None, dicts)
+ dicts.append(self.defaults)
+ return Options(OptionLookup(dicts, branch), self.args)
def load_cmdline(args):
try:
@@ -546,7 +561,7 @@
if opt in ('-h', '--help'):
usage(0)
elif opt == '--cvsroot':
- set('cvsroot', arg)
+ os.environ["CVSROOT"] = arg
elif opt == "--config":
set('config-file', arg)
elif opt == '--no-config':
@@ -605,17 +620,24 @@
def load_configuration(args, branch=None):
cmdline, args = load_cmdline(args)
+ if os.environ.has_key("CVSROOT"):
+ defconfig = os.path.join(os.environ["CVSROOT"],
+ "CVSROOT", "syncmail.conf")
+ else:
+ defconfig = os.path.join("CVSROOT", "syncmail.conf")
if cmdline.has_key('config-file'):
cfgfile = cmdline['config-file']
del cmdline['config-file']
+ elif os.path.isfile(defconfig):
+ cfgfile = defconfig
else:
- cfgfile = "syncmail.conf"
- # cfgfile is specified relative to the CVSROOT directory; we need
- # to transform the path appropriately, since that won't be the
- # current directory when we try to read it. In fact, a wrong
+ cfgfile = None
+ # XXX cfgfile is specified relative to the CVSROOT directory; we
+ # need to transform the path appropriately, since that won't be
+ # the current directory when we try to read it. In fact, a wrong
# config file may exist at the alternate location.
- config = load_configfile(cfgfile, cmdline, branch)
- return Options(config, args)
+ db = ConfigurationDatabase(cfgfile, cmdline, args)
+ return db.get_config(branch)
def main():
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 18:23:53
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv29602
Modified Files:
Tag: new-config-branch
syncmail.conf
Log Message:
cvsroot will not be a setting in the configuration file
Index: syncmail.conf
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/Attic/syncmail.conf,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -d -r1.1.2.1 -r1.1.2.2
--- syncmail.conf 10 Jul 2003 05:40:10 -0000 1.1.2.1
+++ syncmail.conf 11 Jul 2003 18:23:50 -0000 1.1.2.2
@@ -7,7 +7,6 @@
[general]
; miscellaneous
-cvsroot = $CVSROOT
verbose = true
email = true
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 17:51:37
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv25120
Modified Files:
Tag: new-config-branch
syncmail
Log Message:
we only need to set SECTCRE, not OPTCRE
Index: syncmail
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/syncmail,v
retrieving revision 1.36.2.13
retrieving revision 1.36.2.14
diff -u -d -r1.36.2.13 -r1.36.2.14
--- syncmail 11 Jul 2003 17:41:41 -0000 1.36.2.13
+++ syncmail 11 Jul 2003 17:51:33 -0000 1.36.2.14
@@ -496,17 +496,8 @@
r'(?P<header>[^]]+)' # very permissive!
r'\]' # ]
)
- OPTCRE = re.compile(
- r'(?P<option>[^:=\s][^:=]*)' # very permissive!
- r'\s*(?P<vi>[:=])\s*' # any number of space/tab,
- # followed by separator
- # (either : or =), followed
- # by any # space/tab
- r'(?P<value>.*)$' # everything up to eol
- )
# For compatibility with older versions:
__SECTCRE = SECTCRE
- __OPTCRE = OPTCRE
cp = ConfigParser()
# We have to use this old method for compatibility with
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 17:41:44
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv23861
Modified Files:
Tag: new-config-branch
syncmail
Log Message:
- clean up the tagdate field from the CVS/Entries file
- add a note about the non-support of cross-branch commits (applies
only to this branch; the trunk is fine since it doesn't care about
branches)
Index: syncmail
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/syncmail,v
retrieving revision 1.36.2.12
retrieving revision 1.36.2.13
diff -u -d -r1.36.2.12 -r1.36.2.13
--- syncmail 11 Jul 2003 17:21:39 -0000 1.36.2.12
+++ syncmail 11 Jul 2003 17:41:41 -0000 1.36.2.13
@@ -314,6 +314,7 @@
line = string.strip(line)
parts = string.split(line, "/")
_, name, revision, timestamp, options, tagdate = parts
+ tagdate = string.rstrip(tagdate) or None
key = namekey(prefix, name)
try:
entry = mapping[key]
@@ -652,6 +653,10 @@
changes = []
for name, entry in items:
changes.append(entry)
+
+ # XXX Commits can span branches; we haven't allowed for that at
+ # all! This seriously impacts how we handle the configuration
+ # data; need to re-visit.
if config.verbose:
print 'Mailing %s...' % config.people
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 17:21:42
|
Update of /cvsroot/cvs-syncmail/syncmail
In directory sc8-pr-cvs1:/tmp/cvs-serv21033
Modified Files:
Tag: new-config-branch
syncmail
Log Message:
- move loading of the repository directory into Options.__init__()
- add check that we actually have email addresses to send to
- update and re-wrap a comment
Index: syncmail
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/syncmail,v
retrieving revision 1.36.2.11
retrieving revision 1.36.2.12
diff -u -d -r1.36.2.11 -r1.36.2.12
--- syncmail 10 Jul 2003 22:15:00 -0000 1.36.2.11
+++ syncmail 11 Jul 2003 17:21:39 -0000 1.36.2.12
@@ -602,7 +602,14 @@
self.people = string.join(args[1:], COMMASPACE)
else:
self.people = config.get("to")
- self.repodir = os.curdir
+
+ fn = os.path.join("CVS", "Repository")
+ if os.path.isfile(fn):
+ f = open(fn)
+ self.repodir = string.strip(f.readline())
+ f.close()
+ else:
+ self.repodir = os.curdir
def load_configuration(args, branch=None):
cmdline, args = load_cmdline(args)
@@ -622,13 +629,17 @@
def main():
# load the options
config = load_configuration(sys.argv[1:], load_branch_name())
- s = open(os.path.join("CVS", "Repository")).readline()
- config.repodir = string.strip(s)
- # args[0] is the specification containing the files that were
- # modified. The argument actually must be split, with the first component
- # containing the directory the checkin is being made in, relative to
- # $CVSROOT, followed by the list of files that are changing.
+ if not config.people:
+ # Nobody to send mail to!
+ print 'No email addresses provided; exiting.'
+ return
+
+ # config.cvsinfo is the specification containing the files that
+ # were modified. The argument actually must be split, with the
+ # first component containing the directory the checkin is being
+ # made in, relative to $CVSROOT, followed by the list of files
+ # that are changing.
specs = string.split(config.cvsinfo)
if specs[-3:] == ['-', 'Imported', 'sources']:
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 12:27:23
|
Update of /cvsroot/cvs-syncmail/syncmail/tests
In directory sc8-pr-cvs1:/tmp/cvs-serv5865
Modified Files:
Tag: new-config-branch
test_options.py
Log Message:
- make sure the usage-errors actually generated help text
- add tests for explicit requests for help
Index: test_options.py
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/tests/Attic/test_options.py,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -u -d -r1.1.2.3 -r1.1.2.4
--- test_options.py 11 Jul 2003 12:19:29 -0000 1.1.2.3
+++ test_options.py 11 Jul 2003 12:27:18 -0000 1.1.2.4
@@ -3,6 +3,7 @@
# These tests assume that the syncmail script is in the current directory.
import os
+import string
import sys
import unittest
@@ -99,8 +100,9 @@
class UsageErrorTests(unittest.TestCase):
def setUp(self):
- sys.stderr = StringIO()
- sys.stdout = sys.stderr
+ self.sio = StringIO()
+ sys.stderr = self.sio
+ sys.stdout = self.sio
def tearDown(self):
sys.stderr = sys.__stderr__
@@ -109,14 +111,27 @@
def test_simple_option_twice(self):
self.assertRaises(SystemExit, syncmail.load_cmdline,
['-qq'])
+ self.failUnless(string.strip(self.sio.getvalue()))
def test_competing_options(self):
self.assertRaises(SystemExit, syncmail.load_cmdline,
['--config=filename', '--no-config'])
+ self.failUnless(string.strip(self.sio.getvalue()))
def test_double_negation(self):
self.assertRaises(SystemExit, syncmail.load_cmdline,
['--no-config', '--no-config'])
+ self.failUnless(string.strip(self.sio.getvalue()))
+
+ def test_dash_h(self):
+ self.assertRaises(SystemExit, syncmail.load_cmdline,
+ ['-h'])
+ self.failUnless(string.strip(self.sio.getvalue()))
+
+ def test_dash_dash_help(self):
+ self.assertRaises(SystemExit, syncmail.load_cmdline,
+ ['--help'])
+ self.failUnless(string.strip(self.sio.getvalue()))
def test_suite():
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 12:19:33
|
Update of /cvsroot/cvs-syncmail/syncmail/tests
In directory sc8-pr-cvs1:/tmp/cvs-serv4734
Modified Files:
Tag: new-config-branch
test_options.py
Log Message:
more tests of the command line handling
Index: test_options.py
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/tests/Attic/test_options.py,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -d -r1.1.2.2 -r1.1.2.3
--- test_options.py 11 Jul 2003 05:11:00 -0000 1.1.2.2
+++ test_options.py 11 Jul 2003 12:19:29 -0000 1.1.2.3
@@ -56,6 +56,21 @@
def test_load_cmdline_empty(self):
self.assertEqual(syncmail.load_cmdline([]), ({}, []))
+ def test_load_cmdline_simple(self):
+ cmdline = ['abc foo.txt,1.2,1.3', 'me...@ex...']
+ options, args = syncmail.load_cmdline(cmdline)
+ self.assertEqual(options, {})
+ self.assertEqual(args, cmdline)
+
+ def test_load_cmdline_with_options(self):
+ cmdline = ['-qC4', '-u', '--mailhost', 'mail.example.com']
+ options, args = syncmail.load_cmdline(cmdline)
+ self.assertEqual(options, {'verbose': 'false',
+ 'context-lines': '4',
+ 'diff-type': 'unified',
+ 'smtp-server': 'mail.example.com'})
+ self.assertEqual(args, [])
+
def test_load_configuration_empty(self):
config = syncmail.load_configuration([])
self.assertEqual(config.contextlines, 2)
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 05:11:03
|
Update of /cvsroot/cvs-syncmail/syncmail/tests
In directory sc8-pr-cvs1:/tmp/cvs-serv17549
Modified Files:
Tag: new-config-branch
test_options.py
Log Message:
Rework the tests to use the unit testing framework.
Index: test_options.py
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/tests/Attic/test_options.py,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -d -r1.1.2.1 -r1.1.2.2
--- test_options.py 11 Jul 2003 04:26:36 -0000 1.1.2.1
+++ test_options.py 11 Jul 2003 05:11:00 -0000 1.1.2.2
@@ -4,92 +4,110 @@
import os
import sys
+import unittest
from cStringIO import StringIO
import syncmail
-def eq(a, b, msg=None):
- if msg is None:
- msg = "%s != %s" % (`a`, `b`)
- if not a == b:
- raise AssertionError(msg)
+class SimpleOptionTests(unittest.TestCase):
-def raises(exctype, f, *args, **kw):
- try:
- apply(f, args, kw)
- except exctype:
- pass
- else:
- raise AssertionError("expected exception")
+ def test_replacer(self):
+ VARS = {"FOO": "<whack!>"}
-VARS = {"FOO": "<whack!>"}
+ # "variable" replacement
+ replace = syncmail.Replacer(VARS)
-# "variable" replacement
-replace = syncmail.Replacer(VARS)
+ self.assertEqual(replace("abc$FOO-def${SPLAT}"), "abc<whack!>-def")
+ self.assertEqual(replace("$FOO"), "<whack!>")
+ self.assertEqual(replace("$ FOO"), "$ FOO")
+ self.assertEqual(replace("${FOO}"), "<whack!>")
+ self.assertEqual(replace(" ${FOO} "), " <whack!> ")
-eq(replace("abc$FOO-def${SPLAT}"), "abc<whack!>-def")
-eq(replace("$FOO"), "<whack!>")
-eq(replace("$ FOO"), "$ FOO")
-eq(replace("${FOO}"), "<whack!>")
-eq(replace(" ${FOO} "), " <whack!> ")
+ def test_OptionLookup_cascade(self):
+ dicts = [
+ {'common': '1', 'first': 'one'},
+ {'common': '2', 'second': 'two'},
+ {'common': '3', 'third': 'three'},
+ {'common': '4', 'fourth': 'four'},
+ ]
+ options = syncmail.OptionLookup(dicts)
+ self.assertEqual(options.get('common'), '1')
+ self.assertEqual(options.get('first'), 'one')
+ self.assertEqual(options.get('second'), 'two')
+ self.assertEqual(options.get('third'), 'three')
+ self.assertEqual(options.get('fourth'), 'four')
+ self.assertEqual(options.get('missing'), None)
+ self.assertEqual(options.get('common'), '1')
+ self.assertEqual(options.get('third'), 'three')
-# load_cmdline()
-eq(syncmail.load_cmdline([]), ({}, []))
+ def test_OptionLookup_replacements(self):
+ dicts = [
+ {"foo": "bar",
+ "branch": "$BRANCH",
+ "hostname": "$HOSTNAME"},
+ ]
+ options = syncmail.OptionLookup(dicts, "my-branch")
+ self.assertEqual(options.get("branch"), "my-branch")
+ host = os.environ.get("HOSTNAME", syncmail.getfqdn())
+ self.assertEqual(options.get("hostname"), host)
-sys.stderr = StringIO()
-sys.stdout = sys.stderr
-try:
- raises(SystemExit,
- syncmail.load_cmdline, ['-qq'])
- raises(SystemExit,
- syncmail.load_cmdline, ['--config=filename', '--no-config'])
- raises(SystemExit,
- syncmail.load_cmdline, ['--no-config', '--no-config'])
-finally:
- sys.stderr = sys.__stderr__
- sys.stdout = sys.__stdout__
+ def test_load_cmdline_empty(self):
+ self.assertEqual(syncmail.load_cmdline([]), ({}, []))
-# load_configuration()
-config = syncmail.load_configuration([])
-eq(config.contextlines, 2)
-eq(config.verbose, 1)
-eq(config.smtp_server, syncmail.MAILHOST)
-eq(config.smtp_port, syncmail.MAILPORT)
+ def test_load_configuration_empty(self):
+ config = syncmail.load_configuration([])
+ self.assertEqual(config.contextlines, 2)
+ self.assertEqual(config.verbose, 1)
+ self.assertEqual(config.smtp_server, syncmail.MAILHOST)
+ self.assertEqual(config.smtp_port, syncmail.MAILPORT)
-config = syncmail.load_configuration(['-q', '--mailhost=smtp.example.com'])
-eq(config.verbose, 0)
-eq(config.smtp_server, "smtp.example.com")
-eq(config.smtp_port, syncmail.MAILPORT)
+ def test_load_configuration_simple(self):
+ config = syncmail.load_configuration(
+ ['-q', '--mailhost=smtp.example.com'])
+ self.assertEqual(config.verbose, 0)
+ self.assertEqual(config.smtp_server, "smtp.example.com")
+ self.assertEqual(config.smtp_port, syncmail.MAILPORT)
-config = syncmail.load_configuration(['--mailhost=smtp.example.com:8025'])
-eq(config.smtp_server, "smtp.example.com")
-eq(config.smtp_port, 8025)
+ def test_load_configuration_smtp_address(self):
+ config = syncmail.load_configuration(
+ ['--mailhost=smtp.example.com:8025'])
+ self.assertEqual(config.smtp_server, "smtp.example.com")
+ self.assertEqual(config.smtp_port, 8025)
-config = syncmail.load_configuration(['--mailhost=:8025'])
-eq(config.smtp_server, syncmail.MAILHOST)
-eq(config.smtp_port, 8025)
+ config = syncmail.load_configuration(['--mailhost=:8025'])
+ self.assertEqual(config.smtp_server, syncmail.MAILHOST)
+ self.assertEqual(config.smtp_port, 8025)
-# OptionLookup
-dicts = [
- {'common': '1', 'first': 'one'},
- {'common': '2', 'second': 'two'},
- {'common': '3', 'third': 'three'},
- {'common': '4', 'fourth': 'four'},
- ]
-options = syncmail.OptionLookup(dicts)
-eq(options.get('common'), '1')
-eq(options.get('first'), 'one')
-eq(options.get('second'), 'two')
-eq(options.get('third'), 'three')
-eq(options.get('fourth'), 'four')
-eq(options.get('missing'), None)
-eq(options.get('common'), '1')
-eq(options.get('third'), 'three')
-options = syncmail.OptionLookup([{"foo": "bar",
- "branch": "$BRANCH",
- "hostname": "$HOSTNAME"}], "my-branch")
-eq(options.get("branch"), "my-branch")
-eq(options.get("hostname"), os.environ.get("HOSTNAME", syncmail.getfqdn()))
+class UsageErrorTests(unittest.TestCase):
+
+ def setUp(self):
+ sys.stderr = StringIO()
+ sys.stdout = sys.stderr
+
+ def tearDown(self):
+ sys.stderr = sys.__stderr__
+ sys.stdout = sys.__stdout__
+
+ def test_simple_option_twice(self):
+ self.assertRaises(SystemExit, syncmail.load_cmdline,
+ ['-qq'])
+
+ def test_competing_options(self):
+ self.assertRaises(SystemExit, syncmail.load_cmdline,
+ ['--config=filename', '--no-config'])
+
+ def test_double_negation(self):
+ self.assertRaises(SystemExit, syncmail.load_cmdline,
+ ['--no-config', '--no-config'])
+
+
+def test_suite():
+ suite = unittest.makeSuite(SimpleOptionTests)
+ suite.addTest(unittest.makeSuite(UsageErrorTests))
+ return suite
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 05:09:17
|
Update of /cvsroot/cvs-syncmail/syncmail/tests
In directory sc8-pr-cvs1:/tmp/cvs-serv17095
Modified Files:
Tag: new-config-branch
unittest.py
Log Message:
Make some confusing logic even more confusing so this can work with
the Python 1.5.2 versions of isinstance() and issubclass().
Index: unittest.py
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/tests/Attic/unittest.py,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -u -d -r1.1.2.3 -r1.1.2.4
--- unittest.py 11 Jul 2003 04:59:04 -0000 1.1.2.3
+++ unittest.py 11 Jul 2003 05:09:14 -0000 1.1.2.4
@@ -486,7 +486,11 @@
import unittest
if type(obj) == types.ModuleType:
return self.loadTestsFromModule(obj)
- elif (isinstance(obj, (type, types.ClassType)) and
+ elif (type(obj) is types.ClassType and
+ issubclass(obj, unittest.TestCase)):
+ return self.loadTestsFromTestCase(obj)
+ elif (int is type(1) and
+ isinstance(obj, type) and
issubclass(obj, unittest.TestCase)):
return self.loadTestsFromTestCase(obj)
elif type(obj) == types.UnboundMethodType:
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 04:59:07
|
Update of /cvsroot/cvs-syncmail/syncmail/tests
In directory sc8-pr-cvs1:/tmp/cvs-serv15893
Modified Files:
Tag: new-config-branch
unittest.py
Log Message:
Fix typo introduced when making this module compatible with Python
1.5.2.
Index: unittest.py
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/tests/Attic/unittest.py,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -d -r1.1.2.2 -r1.1.2.3
--- unittest.py 11 Jul 2003 04:39:29 -0000 1.1.2.2
+++ unittest.py 11 Jul 2003 04:59:04 -0000 1.1.2.3
@@ -562,7 +562,7 @@
return getattr(self.stream,attr)
def writeln(self, arg=None):
- if args is not None: self.write(arg)
+ if arg is not None: self.write(arg)
self.write('\n') # text-mode streams translate to \r\n if needed
|
|
From: Fred L. D. <fd...@us...> - 2003-07-11 04:39:32
|
Update of /cvsroot/cvs-syncmail/syncmail/tests
In directory sc8-pr-cvs1:/tmp/cvs-serv14072
Modified Files:
Tag: new-config-branch
unittest.py
Log Message:
Make the module compatible with Python 1.5.2.
Index: unittest.py
===================================================================
RCS file: /cvsroot/cvs-syncmail/syncmail/tests/Attic/unittest.py,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -d -r1.1.2.1 -r1.1.2.2
--- unittest.py 11 Jul 2003 04:38:12 -0000 1.1.2.1
+++ unittest.py 11 Jul 2003 04:39:29 -0000 1.1.2.2
@@ -115,7 +115,8 @@
def _exc_info_to_string(self, err):
"""Converts a sys.exc_info()-style tuple of values into a string."""
- return string.join(traceback.format_exception(*err), '')
+ lines = traceback.format_exception(err[0], err[1], err[2])
+ return string.join(lines, '')
def __repr__(self):
return "<%s run=%i errors=%i failures=%i>" % \
@@ -276,7 +277,7 @@
unexpected exception.
"""
try:
- callableObj(*args, **kwargs)
+ apply(callableObj, args, kwargs)
except excClass:
return
else:
@@ -560,8 +561,8 @@
def __getattr__(self, attr):
return getattr(self.stream,attr)
- def writeln(self, *args):
- if args: self.write(*args)
+ def writeln(self, arg=None):
+ if args is not None: self.write(arg)
self.write('\n') # text-mode streams translate to \r\n if needed
|