User: stephent
Date: 06/02/25 14:39:19
Modified: xemacs-builds/stephen ChangeLog xre.py xre.texi xre_data.py
Log:
# 104. Provide trace output for locating news file. Ensure we look in the
# right directory. Add trace output for locating CHANGES file.
# 102. Fix bug in finalize, expect wrong value from validateVersionDictionary.
# 101. Fix bug in audit trail for ChangeLog munging.
# 100. Ensure that finalize is idempotent.
# 77. Do builds in separate directory ./+build. Add to excludeFiles.
# 98. Remove redundant autoconf from makeTarballs, document dependency on
# finalize.
# 97. Improve documentation of abstract.
# 96. Move writeAnnouncements up to before finalize.
# 95. Make finalize update src/depend.
# 94. Read newsfile in writeAnnouncements, not finalize. Fix comment.
# 87. Fix use of dryRun in upload (since products are not currently made,
# they can't be chmod'ed). [Fixed with #93 en passant.]
# 93. Don't try to chmod non-existent files in DRYRUN.
# 89. Move writeAnnouncements out of finalize.
# 88. Fix typo in parseChangesFile.
# 85. Make configure flags a Release attribute.
# 84. Work around font-lock bug by substituting ''' for """.
# 82. prepare method now uses ancestorVersion appropriately.
# 79. Fix version-matching logic for CHANGES files in abstract method.
# 78. Give mnemonic names to regexps in abstract method.
# 72. Raise IOError on missing CHANGES file.
# 71. CHANGES files don't need to be writable for this program.
Revision Changes Path
1.12 +3 -3 XEmacs/xemacs-builds/stephen/ChangeLog
Index: ChangeLog
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs-builds/stephen/ChangeLog,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -p -r1.11 -r1.12
--- ChangeLog 2005/09/15 03:14:08 1.11
+++ ChangeLog 2006/02/25 13:39:16 1.12
@@ -35,11 +35,11 @@
* xre.py: Many small fixes.
- xre_data.py: Use None, not "TRUNK", to indicate head.
+ * xre_data.py: Use None, not "TRUNK", to indicate head.
- xre.texi: Flesh out description of release procedure.
+ * xre.texi: Flesh out description of release procedure.
- xemacs-release.info: New. Compiled version of xre.texi.
+ * xemacs-release.info: New. Compiled version of xre.texi.
2003-08-19 Stephen J. Turnbull <stephen(a)xemacs.org>
1.9 +972 -786 XEmacs/xemacs-builds/stephen/xre.py
Index: xre.py
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs-builds/stephen/xre.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -p -r1.8 -r1.9
--- xre.py 2005/09/15 03:14:09 1.8
+++ xre.py 2006/02/25 13:39:16 1.9
@@ -28,124 +28,177 @@
# a courtesy notice to <stephen(a)xemacs.org> would be appreciated. #
#######################################################################
-# Usage:
+"""xre.py manages releases of the XEmacs core distribution.
-# This code _requires_ Python 2. I run the Python interpreter from
-# M-x shell mode. Then I do "from xre import beta", followed by
-# "beta.doit((21,5,21))" which does most of what's necessary for a
-# release. Note that by default doit() is pretty conservative about
-# what it does. You'll need to create a Developer object for yourself
-# (these are in the data module xre_data.py), and possibly one or more
-# Server or Access objects. The Project, Developer, and Release classes
-# aren't very orthogonal, sorry!
-
-### Kudos:
-# This program is based on Martin Buchholz's excellent Perl program `xre'.
-
-### Apologia:
-# I rewrote it in Python because I understand Python better, and I realized
-# that it would take nearly as much effort to fully understand Martin's
-# program as a Perl program as to rewrite it in Python form, documenting
-# the parts I didn't get on first reading as I go along.
+Usage:
+This code _requires_ Python 2. I run the Python interpreter from
+M-x shell mode. Then I do "from xre import beta", followed by
+"beta.doit((21,5,21))" which does most of what's necessary for a
+release. Note that by default doit() is pretty conservative about
+what it does. You'll need to create a Developer object for yourself
+(these are in the data module xre_data.py), and possibly one or more
+Server or Access objects. The Project, Developer, and Release classes
+aren't very orthogonal, sorry!
+
+Kudos:
+This program is based on Martin Buchholz's excellent Perl program `xre'.
+
+Apologia:
+I rewrote it in Python because I understand Python better, and I realized
+that it would take nearly as much effort to fully understand Martin's
+program as a Perl program as to rewrite it in Python form, documenting
+the parts I didn't get on first reading as I go along.
+
+There remain a large number of bugs and infelicities. See the TODO section
+in the source code."""
+
### TODO
#
-# 2. Many methods refer to xemacs; this should be abstracted.
-# 4. Martin's xre has a better way to do os.system()?
-# 5. Use try ... finally etc to make sure chdirs etc are undone?
-# 6. Add a dictionary of developer aliases to Project, remove projectAlias
-# from Developer class. See comment in Project.updateChangeLogs.
-# 7. Release.upload now uploads to a ./pretest directory where
-# pretests are held.
-# The pretest needs to be announced, and build reports solicited.
-# The pretest would also be available on a special branch,
-# pretest-$major-$minor. The branch would be deleted at commit
-# time, then recreated with the new release as the node. This
-# needs to be implemented
-# Then, after the results are in, the files would be moved to the
-# parent directory. A function to do this is implemented.
-# Pretests could be announced on xemacs-beta, and progress tracked
-# on the web site.
-# 12. Need to deal with CHANGES-{beta,release} in validation procedures.
-# 13. Deal with all FIXMEs.
-# 18. Regularize the dryRun and verbose arguments. (A few odd dryRuns left.)
-# 20. Need to check that ssh-agent is working and/or pserver logged in.
-# 21. The *Carefully functions are probably redundant now.
-# 23. Make error-checking/status returns sane.
-# 25. Make the Release objects self-updating.
-# 26. Use the tuple notation for branches and versions throughout.
-# 27. Should do make check and refuse to do uploads without engineer
-# intervention if anything less than 100%.
-# 42. Access should have "get" and "put" methods, which can be
aliased to
-# some sensible method.
-# 43. Actually display accumulated warnings at some point!
-# 44. Do more testing and submit build reports.
-# 47. Filter makepatch more carefully.
-# 50. Need to merge flags properly. If explicit arg, use that; else if this
-# release defines per-routine default, use that; else if this release
-# defines global default, use that, else if Release class defines
-# per-routine default, use that; else if Release class defines global
-# default, use that; else use per-routine hard-coded default.
-# 51. For uploads, verbose=1 should get a ls -l.
-# 52. Many utilities don't use flags intead of separate args yet.
-# 56. There are still dict arguments not converted to Flags.
-# 59. Collect the formatNamedVariables in announcement generator.
-# 60. Move default values from writeAnnouncements into Release constructor.
-# 62. Fix the CVS tag generation description to work for stable branch, too.
-# 63. Fix CHANGES parsing to pick up headers.
-# 65. Parametrize test builds for different configures.
-# 67. Detect broken builds and abort release process.
-# 69. Refactor: automatic preparation = check out trees, create abstract, output
-# warnings; engineer documentation = update CHANGES, write $VERSION.news;
-# automatically build packages, output warnings, write $VERSION.content
-# in Web; engineer check, update Web index.content; automatically
-# commit code, tag, upload, make public, commit web, send web patch.
-# 71.
+# 2. Many methods refer to xemacs; this should be abstracted.
+# 4. Martin's xre has a better way to do os.system()?
+# 5. Use try ... finally etc to make sure chdirs etc are undone?
+# 6. Add a dictionary of developer aliases to Project, remove projectAlias
+# from Developer class. See comment in Project.updateChangeLogs.
+# 7. Release.upload now uploads to a ./pretest directory where
+# pretests are held.
+# The pretest needs to be announced, and build reports solicited.
+# The pretest would also be available on a special branch,
+# pretest-$major-$minor. The branch would be deleted at commit
+# time, then recreated with the new release as the node. This
+# needs to be implemented
+# Then, after the results are in, the files would be moved to the
+# parent directory. A function to do this is implemented.
+# Pretests could be announced on xemacs-beta, and progress tracked
+# on the web site.
+# 12. Need to deal with CHANGES-{beta,release} in validation procedures.
+# 13. Deal with all FIXMEs.
+# 18. Regularize the dryRun and verbose arguments. (A few odd dryRuns left.)
+# 20. Need to check that ssh-agent is working and/or pserver logged in.
+# 21. The *Carefully functions are probably redundant now.
+# 23. Make error-checking/status returns sane.
+# 25. Make the Release objects self-updating.
+# 26. Use the tuple notation for branches and versions throughout.
+# 27. Should do make check and refuse to do uploads without engineer
+# intervention if anything less than 100%.
+# 42. Access should have "get" and "put" methods, which can be
aliased to
+# some sensible method.
+# 43. Actually display accumulated warnings at some point!
+# 44. Do more testing and submit build reports.
+# 47. Filter makepatch more carefully.
+# 50. Need to merge flags properly. If explicit arg, use that; else if this
+# release defines per-routine default, use that; else if this release
+# defines global default, use that, else if Release class defines
+# per-routine default, use that; else if Release class defines global
+# default, use that; else use per-routine hard-coded default.
+# 51. For uploads, verbose=1 should get a ls -l.
+# 52. Many utilities don't use flags intead of separate args yet.
+# 56. There are still dict arguments not converted to Flags.
+# 59. Collect the formatNamedVariables in announcement generator.
+# 60. Move default values from writeAnnouncements into Release constructor.
+# 62. Fix the CVS tag generation description to work for stable branch, too.
+# 63. Fix CHANGES parsing to pick up headers.
+# 65. Parametrize test builds for different configures.
+# 67. Detect broken builds and abort release process.
+# 69. Refactor: automatic prep = check out trees, create abstract, output
+# warnings; engineer documentation = update CHANGES, write $VERSION.news;
+# automatically build packages, output warnings, write $VERSION.content
+# in Web; engineer check, update Web index.content; automatically
+# commit code, tag, upload, make public, commit web, send web patch.
+# 73. Handle headers in CHANGES file.
+# 74. Specify CHANGES and ChangeLog file formats for abstract method.
+# 75. Convert abstract method to return list of lines, or perhaps a tree
+# structure for sections, etc., parsing headers. This involves
+# reorganizing writeAnnouncements, changesToHTML, changesToText, abstract,
+# and others.
+# 76. Allow user-defined formats for abstract method.
+# 80. Find some way to generate heralds and regexps from the same spec.
+# 81. Rename the Release class to Branch or Series, since most of the
+# information is common from release to release.
+# 83. Move the newsfile into CHANGES file.
+# 86. Change dryRun (boolean) to mode, with values RELEASE, DRYRUN, LOCAL,
+# PLAN. RELEASE means to do uploads, etc. DRYRUN means to build all
+# products, but do nothing to change the archive host. LOCAL is like
+# DRYRUN, but uses existing tarballs where available, falling back to
+# updating from remote CVS. PLAN means to produce a transcript of what
+# would have been done, making assumptions about intermediate results
+# that would change execution path.
+# 90. Refactor abstract and writeAnnouncements. abstract() should only
+# need the version spec and a reasonably up-to-date tree.
+# 91. Make vertical spacing in changesToText more robust.
+# 92. Do diffs and tarballs as early as possible to avoid creating garbage.
+# 99. Should build directory be sibling instead of subdirectory?
+# 103. Provide for comments in CHANGES-beta.
+# 105.
### DONE
-# 70. Update xemacs_extra_name and xemacs_release_date in version.sh.
-# 68. Regularize and document the announcement construction parameters.
-# 66. Ensure configure is up to date before making tarbabies and testing.
-# 64. Fix test build to work right with autoconf changes.
-# 61. Review: are all variables initialized in write announcements?
-# 58. Abstract and refactor the announcement generator.
-# 57. Update the header comment.
-# 55. Deal with the src/depends file per Martin.
-# 54. Get rid of unnecessary shape attribute in HTML href tags.
-# 53. Fix dict arg not converted to Flags bug.
-# 49. Fix the flags argument not used in body bug.
-# 48. Fix some cvs method bugs, including deepcopy bug in xre_data.tester.
-# 46. Exclude Emacs backup files.
-# 45. Quote --exclude globs in makepatch and tar commands.
-# 41. Fix HTML escape utility.
-# 40. Completely rewrite parseChangesFile.
-# 39. Generalize getCodenameFromFile.
-# 38. Break out makeUploadList method.
-# 37. Set up uploads for FTP READMEs.
-# 34. Create Flags class to handle global verbosity and dryRun, etc.
-# 35. Improve class Access.
-# 36. Implement Release.abstract (and immediately obsolete?)
-# 33. Implement announcement generators for mail and HTML.
-# 31. Lots of small fixes.
-# 32. Move upload of READMEs from Release.upload to Release.makePublic.
-# 30. Add Access for up/download of READMEs.
-# 29. Unify tarball and patchkit exclude generation.
-# 9. Move the object initializations out of this file.
-# 28. Should run xemacs and open an X frame as a quick test.
-# 22. Move the CHANGES-file spec into the Release class.
-# 29. Move versionFormat to Release class; people WILL fuck with that file.
-# 24. Use Python statvfs to check free space instead of df.
-# 16. Move staging directory attribute from Project to Developer class.
-# 19. Remove space check from Release validation.
-# 17. Regularize the dryRun and verbose arguments. (Mostly done.)
-# 8. There should be a host class to hold info about directories and
-# anonymous user authorization.
-# 15. Change dryrun argument names to "dryRun".
-# 14. Use keywords not positional arguments in higher-level functions.
-# 10. Update methods to pass dryRun parameters to execAnd*() functions.
-# 11. Rename class Status as class Filter.
-# 1. Many methods do os.chdir(self.project.stage). Probably this should
-# be done in initialization, once. ## Not is better, more robust.
-# 3. Change the insane __init__ arglists to use keywords.
+# 104. Provide trace output for locating news file. Ensure we look in the
+# right directory. Add trace output for locating CHANGES file.
+# 102. Fix bug in finalize, expect wrong value from validateVersionDictionary.
+# 101. Fix bug in audit trail for ChangeLog munging.
+# 100. Ensure that finalize is idempotent.
+# 77. Do builds in separate directory ./+build. Add to excludeFiles.
+# 98. Remove redundant autoconf from makeTarballs, document dependency on
+# finalize.
+# 97. Improve documentation of abstract.
+# 96. Move writeAnnouncements up to before finalize.
+# 95. Make finalize update src/depend.
+# 94. Read newsfile in writeAnnouncements, not finalize. Fix comment.
+# 87. Fix use of dryRun in upload (since products are not currently made,
+# they can't be chmod'ed). [Fixed with #93 en passant.]
+# 93. Don't try to chmod non-existent files in DRYRUN.
+# 89. Move writeAnnouncements out of finalize.
+# 88. Fix typo in parseChangesFile.
+# 85. Make configure flags a Release attribute.
+# 84. Work around font-lock bug by substituting ''' for """.
+# 82. prepare method now uses ancestorVersion appropriately.
+# 79. Fix version-matching logic for CHANGES files in abstract method.
+# 78. Give mnemonic names to regexps in abstract method.
+# 72. Raise IOError on missing CHANGES file.
+# 71. CHANGES files don't need to be writable for this program.
+# 70. Update xemacs_extra_name and xemacs_release_date in version.sh.
+# 68. Regularize and document the announcement construction parameters.
+# 66. Ensure configure is up to date before making tarbabies and testing.
+# 64. Fix test build to work right with autoconf changes.
+# 61. Review: are all variables initialized in write announcements?
+# 58. Abstract and refactor the announcement generator.
+# 57. Update the header comment.
+# 55. Deal with the src/depends file per Martin.
+# 54. Get rid of unnecessary shape attribute in HTML href tags.
+# 53. Fix dict arg not converted to Flags bug.
+# 49. Fix the flags argument not used in body bug.
+# 48. Fix some cvs method bugs, including deepcopy bug in xre_data.tester.
+# 46. Exclude Emacs backup files.
+# 45. Quote --exclude globs in makepatch and tar commands.
+# 41. Fix HTML escape utility.
+# 40. Completely rewrite parseChangesFile.
+# 39. Generalize getCodenameFromFile.
+# 38. Break out makeUploadList method.
+# 37. Set up uploads for FTP READMEs.
+# 34. Create Flags class to handle global verbosity and dryRun, etc.
+# 35. Improve class Access.
+# 36. Implement Release.abstract (and immediately obsolete?)
+# 33. Implement announcement generators for mail and HTML.
+# 31. Lots of small fixes.
+# 32. Move upload of READMEs from Release.upload to Release.makePublic.
+# 30. Add Access for up/download of READMEs.
+# 29. Unify tarball and patchkit exclude generation.
+# 9. Move the object initializations out of this file.
+# 28. Should run xemacs and open an X frame as a quick test.
+# 22. Move the CHANGES-file spec into the Release class.
+# 29. Move versionFormat to Release class; people WILL fuck with that file.
+# 24. Use Python statvfs to check free space instead of df.
+# 16. Move staging directory attribute from Project to Developer class.
+# 19. Remove space check from Release validation.
+# 17. Regularize the dryRun and verbose arguments. (Mostly done.)
+# 8. There should be a host class to hold info about directories and
+# anonymous user authorization.
+# 15. Change dryrun argument names to "dryRun".
+# 14. Use keywords not positional arguments in higher-level functions.
+# 10. Update methods to pass dryRun parameters to execAnd*() functions.
+# 11. Rename class Status as class Filter.
+# 1. Many methods do os.chdir(self.project.stage). Probably this should
+# be done in initialization, once. ## Not is better, more robust.
+# 3. Change the insane __init__ arglists to use keywords.
### imports
@@ -155,7 +208,7 @@ import os
from statvfs import F_FRSIZE, F_BAVAIL
from string import split, strip, replace
from time import strftime, gmtime, time
-from re import compile, match, search, IGNORECASE
+import re
from os.path import dirname, isdir, abspath
from types import *
from copy import copy
@@ -409,6 +462,8 @@ class Project:
If verbose, warn about incomplete or invalid entries.
FIXME: currently does nothing."""
+ if not "+build" in self.excludeFiles['always']:
+ self.excludeFiles['always'].append("+build")
self.valid = 1
@@ -455,7 +510,7 @@ class Flags:
class Release:
- """Represents a release of a software project.
+ """Represents a series of releases of a software project.
Successful instantiation of a release creates an object with methods
for finalizing the release in CVS with appropriate ChangeLog entries,
@@ -467,22 +522,22 @@ class Release:
All paths below are relative to the project staging directory.
Initializer arguments:
- cvsTag CVS branch tag for checkout and update.
- version Tuple giving current version. #### obsolete
ancestorVersion Tuple giving version from which branch forked.
+ tipCVSTag CVS tag for tip of branch.
codenameFile Path to file containing version/codename pairs.
project Project object.
engineer Developer object.
isBeta 0 for public release, 1 for beta release.
Defaulted according to odd/even rule, but can be
overridden explicitly.
- changesFile Defaulted according to odd/even rule (_not_
- isBeta), but can be overridden explicitly.
+ changesFile Defaulted according to isBeta, but can be
+ overridden explicitly.
branchPointTag Tag to branch from for initial public release.
versionStandardFields Variable names expected to be in version.sh.
Initializations written to file in order of this
attribute, followed by versionRogueFields.
versionRequiredFields Variable names required in version.sh.
+ configureFlags Options for the configure script.
reliability Used by writeAnnouncements.
announceAddress
intro Used by writeAnnouncements.
@@ -492,6 +547,9 @@ class Release:
download part, use the empty string.
Attributes:
+ CVSTag CVS branch tag for checkout and update.
+ previousCVSTag CVS branch tag for checkout and update.
+ version Tuple giving current version.
previousVersion Tuple giving previous version.
versionString String in dotted triple format (1.2.3),
indicates current version. #### advisory?
@@ -507,6 +565,8 @@ class Release:
postamble which probably should
header not be changed.
Public methods:
+ validate Verify internal consistency of the object.
+ setVersion Set version-specific information.
prepare Create a clean source tree, updated to current
state of CVS branch, verify consistency.
finalize Finalize by adding appropriate ChangeLogs and
@@ -519,19 +579,20 @@ class Release:
branch for a .0 release.
upload Upload tarball(s), patch, and PGP signatures to
distribution host.
- announce Post announcements to (eg) xemacs-announce,
- the home page, and FreshMeat.
+ announce Post announcements to announce mailing list,
+ the home page, FreshMeat, etc.
doit Perform the above actions in order."""
def __init__ (self,
- cvsTag,
+ tipCVSTag,
ancestorVersion,
codenameFile,
project,
engineer,
versionStandardFields,
versionRequiredFields,
+ configureFlags = None,
tagTail = None,
isBeta = None,
changesFile = None,
@@ -548,19 +609,20 @@ class Release:
self.state = None
self.project = project
self.engineer = engineer
- self.cvsTag = cvsTag
+ self.tipCVSTag = tipCVSTag
if tagTail is None:
self.tagTail = ""
else:
self.tagTail = tagTail
self.version = None
- self.ancestorVersion = ancestorVersion # redundant?
+ self.ancestorVersion = ancestorVersion
self.codenameFile = codenameFile
self.isBeta = isBeta
self.changesFile = changesFile
self.branchPointTag = branchPointTag
self.versionStandardFields = versionStandardFields
self.versionRequiredFields = versionRequiredFields
+ self.configureFlags = configureFlags
self.warnings = []
self.reliability = reliability
self.announceAddress = announceAddress
@@ -576,33 +638,70 @@ class Release:
# need a function to validate version in a tree
def setVersion (self, version):
- """Set version information for a release object.
+ '''Set version information for a release object.
self is a Release object.
version is a version spec, normally a tuple of integers.
- Also sets some information derived from version if not
specified."""
+ In XEmacs, the version proper has three integer components. For some
+ releases there may be a "tag tail" (eg, for stable releases there may
+ be release candidates labeled "rcN") as a fourth component. The tag
+ tail should be a string.
+ Attributes set include:
+ version current version
+ stem name of directory for release tree
+ CVSTag CVS tag for release (use tipCVSTag for update)
+ previousVersion comparison version (for patches)
+ previousStem name of directory for comparison version
+ previousCVSTag CVS tag to checkout comparison version
+ versionDir location of tarballs on distribution host
+ Attributes set if specified:
+ tagTail the release candidate serial number
+ Attributes set only if uninitialized include:
+ isBeta whether release is beta or stable
+ changesFile name of file containing brief changes.
+ Also sets some information derived from version if not specified.'''
- self.version = version
p = self.project
- if version[2]:
+ self.version = version
+ if version[2] != 0:
self.previousVersion = version[0:2] + (version[2]-1,)
else:
- self.previousVersion = ancestorVersion
- self.versionString = "%d.%d.%d" % version
- self.stem = "%s-%d.%d.%d" % ((p.alias,) + self.version)
- self.previousStem = "%s-%d.%d.%d" % ((p.alias,) +
self.previousVersion)
+ self.previousVersion = self.ancestorVersion
+ self.versionString = "%d.%d.%d" % version[0:3]
+ self.stem = self.makeStem(self.version)
+ self.CVSTag = self.makeCVSTag(self.version)
+ if len(version) == 4:
+ self.tagTail = version[3]
+ self.previousStem = self.makeStem(self.previousVersion)
+ self.previousCVSTag = self.makeCVSTag(self.previousVersion)
self.versionDir = "%s-%d.%d" % ((p.alias,) + self.version[0:2])
- if self.isBeta == None:
+ if self.isBeta is None:
self.isBeta = self.version[1] % 2
- if self.changesFile != None:
+ if self.changesFile is not None:
pass
- elif self.version[1] % 2:
+ elif self.isBeta:
self.changesFile = "CHANGES-beta"
else:
self.changesFile = "CHANGES-release"
+ # FIXME: probably ought to be a project method
+ def makeCVSTag (self, version):
+ """Make a CVS tag name for version.
+ version is a tuple with the first three components integers."""
+ return "r%d-%d-%d" % version[0:3]
+
+
+ # FIXME: probably ought to be a project method
+ def makeStem (self, version):
+ """Make a stem name corresponding to version.
+ Stem names are used as components of product names (eg, tarballs)
+ and for directories to store project trees we work with.
+ version is a tuple with the first three components integers."""
+ return "%s-%d.%d.%d" % ((self.project.alias,) + version[0:3])
+
+
def doit (self, version, reallyCheckout=0, dontSign=0):
"""Automated release procedure.
@@ -627,12 +726,11 @@ class Release:
packageFlags=Flags(defaultFlags)
packageFlags.set('verbose',2)
- self.setVersion(version[0:3])
- if len(version) == 4:
- self.tagTail = "rc%d" % version[3]
+ self.setVersion(version)
self.validate()
self.prepare(flags=defaultFlags)
self.finalize()
+ self.writeAnnouncements()
self.abstract()
self.package(flags=packageFlags)
self.check()
@@ -692,16 +790,13 @@ to the Release object in order."""
if verbose: print "XRE> Preparing a source tree in " + e.stage
os.chdir(e.stage)
- # 1. Remove existing trees and GPG signatures
- if verbose: print "XRE> 1. Remove existing trees and check space"
+ # 1. Remove existing trees, patches, and GPG signatures
+ if verbose: print "XRE> 1. Remove existing trees and check space."
# FIXME: should check for tarball if noNet
- execAndTrace("rm -rf " + self.previousStem)
- execAndTrace("rm -f *%d.%d.%d*.asc" % self.version)
if dryRun == 0:
execAndTrace("rm -rf " + self.stem)
- execAndTrace ("rm -f *%d.%d.%d*.tar*" % self.version)
+ execAndTrace("rm -rf " + self.previousStem)
# .patch immediately follows version
- execAndTrace ("rm -f *%d.%d.%d.patch*" % self.version)
# FIXME: this works here, but it's not the right thing
# need merge/override/default operations
flags.set('raiseOnInsufficient', 1)
@@ -709,44 +804,92 @@ to the Release object in order."""
else:
self.checkNoSpace(flags=flags)
- # 2. Checkout the current tip of the CVS branch. (Theoretically
- # we could reuse a work area, but this is safest.)
- access = copy(p.cvsRO)
- access.merge(e.cvsRO)
- access.query = "checkout -P" # Prune empty directories
- access.fragment = self.cvsTag
-
+ if verbose: print "XRE> 2. Prepare tree for release."
if dryRun == 0:
- updateCarefully(access.cvs(stage=self.stem,module=p.cvsModule))
+ # Checkout the current tip of the CVS branch. (Theoretically
+ # we could reuse a work area---Martin did---but this is safest.)
+ self.makeTreeForVersionFromCVS(None)
else:
- # FIXME: need to barf here if the checked-out tree doesn't exist.
+ self.validateTreeForVersion(self.version)
pass
+
+ # We do this after creating the tree, because we'd like to be
+ # able to use that tarball (although currently we don't).
+ if verbose: print "XRE> 3. Remove files we will regenerate."
+ execAndTrace("rm -f *%d.%d.%d*.asc" % self.version)
+ execAndTrace("rm -f *%d.%d.%d.patch*" % self.version)
+ execAndTrace("rm -f *%d.%d.%d*.tar*" % self.version)
- if verbose: print "3. (Omitted, probably deprecated.)"
- # 3. Check that version.sh is consistent with (ie, immediate
- # predecessor of) the release in preparation.
- # Note: done in method finalize()
+ if verbose: print "XRE> 4. Prepare the previous release tree."
+ previous = self.previousVersion
+ if dryRun == 0:
+ # The try is awkward. The idea is that currently an IOError
+ # really means the tarball was corrupt as the tree doesn't
+ # validate. So remove the corrupt tree and try CVS.
+ try:
+ if not self.makeTreeForVersionFromTarball(previous):
+ self.makeTreeForVersionFromCVS(previous)
+ except IOError:
+ execAndTrace("rm -rf " + self.previousStem)
+ self.makeTreeForVersionFromCVS(previous)
+ else:
+ self.validateTreeForVersion(previous)
+
+ def validateTreeForVersion (self, version, flags={}):
+ """Validates tree and raises IOError if invalid.
+ Currently it only checks for existence and readability of the tree's
+ version.sh file.
+ This method can be applied to reuse an existing tree, but should only
+ be used to test logic; it cannot reliably produce a clean
release."""
+
+ versionfile = "%s/version.sh" % self.makeStem(version)
+ if not os.access(versionfile,os.R_OK):
+ raise IOError, "%s is not readable" % versionfile
+
+ def makeTreeForVersionFromTarball (self, version, flags={}):
+ """Create a tree for version by unpacking a release tarball.
+ Returns True if successful, False on recoverable failure
+ (currently, only tarball not found).
+ Calls validateTreeForVersion (raises IOError if invalid).
+ This method is inappropriate for the release tree."""
- # 4. Prepare the previous release tree. (FIXME: For x.y.0 releases,
- # use ancestorVersionString.)
+ # FIXME: this algorithm probably doesn't work for nonnull tagTail
if self.isBeta:
- previousTarball = self.previousStem + ".tar.gz"
+ tarball = self.makeStem(version) + ".tar.gz"
else:
- previousTarball = self.previousStem + "-src.tar.gz"
+ tarball = self.makeStem(version) + "-src.tar.gz"
- if not os.access(previousTarball,os.R_OK):
- access.fragment = "r%d-%d-%d" % self.previousVersion
- updateCarefully(access.cvs(stage=self.previousStem,
- module=p.cvsModule))
+ if os.access(tarball,os.R_OK):
+ execAndTrace("tar xvzf " + tarball)
else:
- execAndTrace("tar xvzf " + previousTarball)
+ return False
- # 5. check for a x.y.z.news file, and slurp it in if present
- if os.access ("%d.%d.%d.news" % self.version, os.R_OK):
- f = open ("%d.%d.%d.news" % self.version)
- self.news = f.read()
- f.close()
+ self.validateTreeForVersion(version)
+ return True
+
+
+ def makeTreeForVersionFromCVS (self, version=None, flags={}):
+ """Create a tree for version by checking out the given version.
+ If version is None or omitted, checkout the CVS branch.
+ Returns True if successful, False on recoverable failure.
+ (Currently no recoverable failure conditions are defined.)
+ Calls validateTreeForVersion (raises IOError if invalid).
+ This is the canonical method for release trees."""
+
+ access = copy(self.project.cvsRO)
+ access.merge(self.engineer.cvsRO)
+ access.query = "checkout -P" # Prune empty directories
+ if version is None:
+ version = self.version
+ access.fragment = self.tipCVSTag
+ else:
+ access.fragment = self.makeCVSTag(version)
+ updateCarefully(access.cvs(stage=self.makeStem(version),
+ module=self.project.cvsModule))
+ self.validateTreeForVersion(version)
+ return True
+
## Finalizing the CVS tree
# Finalizing is different depending on whether the release is a beta
@@ -778,17 +921,31 @@ to the Release object in order."""
# different strategy here, it seems.
def finalize (self, flags={ 'dryRun' : 0, 'verbose' : 1 }):
- """Update configure, heralds in ChangeLogs, and version in
version.sh.
+ """Update configure, src/depend, heralds in ChangeLogs, and
+ version in version.sh.
- Generate release announcements.
+ This function is quasi-idempotent. If it has already been executed,
+ it will change the timestamp on configure, and nothing else.
+ This function depends only on prepare."""
- Do _not_ commit or tag here because that is externally
visible."""
+ # Do _not_ commit or tag here because that is externally visible.
flags = Flags(flags)
dryRun = flags.val('dryRun')
verbose = flags.val('verbose')
if verbose:
+ print "Updating src/depend ... ",
+ os.chdir(self.engineer.stage + "/" + self.stem + "/src")
+ # This script is idempotent.
+ os.system("rm -f depend.tmp" +
+ " && perl ./make-src-depend > depend.tmp" +
+ " && if cmp -s depend depend.tmp; then rm -f
depend.tmp;" +
+ " else rm -f depend && mv depend.tmp depend; fi")
+ if verbose:
+ print "done."
+
+ if verbose:
print "Updating configure: ",
# NB: cvs will not commit unless it's different (according to diff)
os.chdir(self.engineer.stage + "/" + self.stem)
@@ -815,201 +972,468 @@ to the Release object in order."""
if verbose:
print "Updating version file ..."
self.parseVersionFile()
- self.validateVersionDictionary()
- self.writeVersionFile()
-
- if verbose:
- print "Generating announcements ..."
- self.writeAnnouncements()
+ if self.validateVersionDictionary() == 0:
+ self.writeVersionFile()
- def abstract (self, flags=Flags({})):
- """Create documentation for release announcements.
- Extract recent logs and other info useful in announcements.
- Write them to files in the staging directory.
+ def writeAnnouncements (self, flags={}):
+ """Write #.#.#.content and #.#.#.announce files in the staging
+ directory.
- Depends on `finalize' to determine codename."""
+ Requires codename and herald to be previously generated."""
- dryRun = flags.val('dryRun')
- noNet = flags.val('noNet')
+ flags = Flags(flags)
verbose = flags.val('verbose')
-
- p = self.project
- e = self.engineer
-
- download = copy(p.download)
- download.merge(e.download)
+ if verbose:
+ print "Generating announcements ..."
- os.chdir(e.stage)
+ map = {}
+ if self.announceAddress:
+ map['announceAddress'] = self.announceAddress
+ else:
+ map['announceAddress'] = 'xemacs-announce(a)xemacs.org'
+ map['herald'] = self.herald[:-1] # strip the period
+ #### These probably have ...String versions.
+ map['version'] = "%d.%d.%d" % self.version
+ map['previousVersion'] = "%d.%d.%d" % self.previousVersion
+ map['codename'] = self.codename
+ map['previousCodename'] = self.getCodenameFromFile
(self.previousVersion)
+ map['series'] = self.getSeriesFromCodenameFilename ()
+ if self.reliability:
+ map['reliability'] = self.reliability
+ else:
+ map['reliability'] = 'beta'
+ map['engineer'] = self.engineer.fullName
+ map['role'] = self.engineer.comment
+ map['alias'] = self.engineer.projectAlias
+ map['domain'] = self.project.mailDomain
+ #### This won't work for 21.4!
+ map['releaseSpec'] = "-r r%d-%d-%d" % self.version
+ map['currentSpec'] = "-r r%d-%d-current-beta" %
self.version[:2]
+ map['branchSpec'] = "-A"
+ ordinals = [ 'first', 'second', 'third',
'fourth', 'fifth', 'sixth',
+ 'seventh', 'eighth', 'ninth',
'tenth', 'eleventh',
+ 'twelfth', 'thirteenth', 'fourteenth',
'fifteenth',
+ 'sixteenth', 'seventeenth', 'eighteenth',
'nineteenth',
+ 'twentieth', 'twenty-first',
'twenty-second',
+ 'twenty-third', 'twenty-fourth',
'twenty-fifth',
+ 'twenty-sixth', 'twenty-seventh',
'twenty-eighth',
+ 'twenty-ninth', 'thirtieth',
'thirty-first',
+ 'thirty-second', 'thirty-third',
'thirty-fourth',
+ 'thirty-fifth', 'thirty-sixth',
'thirty-seventh',
+ 'thirty-eighth', 'thirty-ninth', 'fortieth'
]
+ map['ordinal'] = ordinals[self.version[2]]
- # Down and update FTP READMEs for public releases.
- for filename in ['.message','README']:
- localname = self.versionString+"."+filename
+ # genpage wrapper
+ # **** You probably should NOT replace these. ****
+ if self.postamble is not None:
+ postamble = self.postamble
+ else:
+ postamble = "</pre>\n\n"
+ if self.preamble is not None:
+ preamble = self.preamble
+ else:
+ preamble = formatNamedVariables ('''\
+%title%
+%(herald)s
+%author%
+automatically generated (with release announcement) by xre.py
+%main%
+ <h1><a
name="announcement">%(herald)s</a></h1>
+ <p>goto announcement,
+ <a href="#summary">summary</a>,
+ <a href="#changes">changes</a></p>
+ <pre xml:space="preserve">
+''', map)
- if os.access (localname, os.W_OK) or os.access (".", os.W_OK) \
- and not os.access (localname, os.F_OK):
- cmd = download.scp (source=filename, target=localname)
- execAndTrace (cmd, dryRun + noNet, verbose)
- else:
- print "Couldn't update %s: not writable." % filename
+ # **** You usually shouldn't need to replace this. ****
+ if self.header is not None:
+ header = formatNamedVariables (self.header, map)
+ else:
+ header = formatNamedVariables ('''\
+To: %(announceAddress)s
+From: "%(engineer)s, %(role)s" <%(alias)s@%(domain)s>
+Subject: %(herald)s.
+Organization: The XEmacs Project
+''', map)
- # FIXME: global replace is not what we want here
- if os.access (localname, os.R_OK):
- f = open (localname)
- old = f.read ()
- f.close ()
- new = replace (old, "%d.%d.%d" % self.previousVersion,
- self.versionString)
- f = open (localname, "w")
- f.write (new)
- f.close ()
- else:
- print "Couldn't update %s: not readable." % filename
+ if self.intro is not None:
+ intro = formatNamedVariables (self.intro, map)
+ else:
+ intro = formatNamedVariables ('''\
+* %(herald)s.
+ "%(codename)s" is the %(ordinal)s in the %(series)s series.
- re0 = r'XEmacs.* (\d+)\.(\d+)(\.|-beta)(\d+).*is released'
- re1 = r'^to( XEmacs)? (\d+)\.(\d+)\.(\d+) "(.+)"$'
- os.chdir(e.stage + "/" + self.stem)
- # handle CHANGES-{beta,release}
- lines = ['Brief summary of Changes to %s "%s"\n\n' %
- (self.versionString,self.codename)]
- if self.isBeta and os.access ("CHANGES-beta", os.W_OK):
- changesFile = "CHANGES-beta"
- else:
- changesFile = "CHANGES-release"
- # FIXME: handle missing or empty changesFile
- f = open (changesFile, "r")
- line = f.readline()
- if verbose > 1:
- print line
- m = match(re1, line)
- while line and not m:
- line = f.readline()
- if verbose > 1:
- print line
- m = match(re1, line)
- # codename may have a trailing gloss
- # FIXME: this test is badly broken
- if (not match(m.group(5),self.codename) or
- int(m.group(4)) != self.version[2] or
- int(m.group(3)) != self.version[1] or
- int(m.group(2)) != self.version[0]):
- # FIXME: should be able to make this exception a warning
- if int(m.group(4)) != self.version[2] - 1:
- raise ValueError, "Incorrect version in " + changesFile
- else:
- # FIXME: should collect serious warnings in a list for
- # regurgitation at end
- print changesFile + " is incomplete! Don't upload!!"
- line = f.readline()
- while line:
- if verbose > 1:
- print line
- # FIXME: maybe this should be less fuzzy
- m = match(re1, line)
- if m:
- break
- else:
- lines.append(line)
- line = f.readline()
- f.close()
+The successor to XEmacs %(previousVersion)s "%(previousCodename)s",
"%(codename)s" adds ''', map)
- # handle ChangeLogs
- for log in self.findChangeLogs ("."):
- if verbose > 0:
- print log
- # consistent with Martin's format
- lines.append("-------- ChangeLog entries from %s --------\n\n" \
- % log)
- f = open(log,"r")
- line = f.readline()
- while line:
- if verbose > 1:
- print line
- # FIXME: maybe this should be less fuzzy
- m = search(re0, line)
- if (m and
- (int(m.group(4)) != self.version[2] or
- int(m.group(2)) != self.version[1] or
- int(m.group(1)) != self.version[0])):
- lines = lines[:-2]
- break
- else:
- lines.append(line)
- line = f.readline()
+ if verbose: print "XRE> 5. Read x.y.z.news file if available."
+ stage = self.engineer.stage
+ newsbase = "%d.%d.%d.news" % self.version
+ newsfile = "%s/%s" % (stage,newsbase)
+ if os.access(newsfile, os.R_OK):
+ f = open(newsfile)
+ self.news = f.read()
f.close()
- f = open ("%s/%d.%d.%d-Abstract" % ((e.stage,) + self.version),
"w")
- for line in lines:
- f.write(line)
- f.write("""\
-<!-- Keep this comment at the end of the file
-Local variables:
-mode: xml
-sgml-omittag:nil
-sgml-shorttag:nil
-sgml-namecase-general:nil
-sgml-general-insert-case:lower
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:2
-sgml-indent-data:t
-sgml-parent-document:("../template.html" "html" "body"
"table" "tr" "td")
-sgml-exposed-tags:nil
-sgml-local-catalogs:nil
-sgml-local-ecat-files:nil
-End:
--->
-""")
- f.close()
+ if verbose: print "XRE> Interpolated %s." % newsfile
+ else:
+ print "XRE> Found no %s in %s." % (newsbase,stage)
+ if self.news is not None:
+ news = formatNamedVariables (self.news, map)
+ else:
+ news = "<INSERT NEWS HERE>"
- def package (self, flags=Flags({})):
- """Create distribution ready for upload.
+ if self.blurb is not None:
+ blurb = formatNamedVariables (self.blurb, map)
+ else:
+ blurb = '''\
+The first release in this series, XEmacs 21.4.0 "Solid Vapor",
+contained a large number of improvements and extensions to the current
+stable version, XEmacs 21.1.14. For more information about the
+OXYMORON series, see etc/NEWS, the initial release announcement
- Distribution includes patch, tarball(s), and PGP signatures.
+
http://www.xemacs.org/Releases/21.4.0.html
- Flags observed are verbose, dontAsk, and dryRun."""
+and the release planning page,
- dryRun = flags.val('dryRun')
- dontAsk = flags.val('dontAsk')
- verbose = flags.val('verbose')
-
- if dryRun and verbose:
- print "Dry run, not making tarballs."
- elif dontAsk and verbose:
- print "Dry run, making tarballs but not signing."
-
- # cd to staging directory
- os.chdir(self.engineer.stage)
+
http://www.xemacs.org/Releases/Public-21.2/
- # make patch
- # do it before making tarballs, which generates .elcs and .infos
- newspace = self.stem
- oldspace = self.previousStem
- patchkit = self.previousStem + "-" + self.versionString +
".patch"
+For general information about XEmacs, the developers, and the user
+community, see our home page,
- findcmd = "find . -name CVS -prune -or -type f -print > MANIFEST"
+
http://www.xemacs.org/'''
- if verbose:
- print "cd to " + self.previousStem
- os.chdir(self.previousStem)
- execAndTrace(findcmd, dryRun, verbose)
+ if self.disclaimer is not None:
+ disclaimer = formatNamedVariables (self.disclaimer, map)
+ else:
+ disclaimer = formatNamedVariables ('''\
+* XEmacs %(version)s is "%(reliability)s" software.
- if verbose:
- print "cd to ../" + self.stem
- os.chdir("../" + self.stem)
- execAndTrace(findcmd, dryRun, verbose)
+The usual "no warranty" disclaimer (see etc/WARRANTY, sections 10 and
+11) applies. However, we are now experimenting with a level of
+stability intermediate between "beta" and "stable", dubbed
"gamma".
+At this point all the developers and our beta testers trust the 21.4
+code base with all their editing needs. Many have found it
+sufficiently stable that they have moved on to the development branch
+again in search of some excitement.
- os.chdir("..")
+After several months of testing, XEmacs %(version)s has been shown
+sufficiently stable to be recommended to all users. However, there
+still remain a few outstanding problems that must be fixed before we
+retire 21.1.''', map)
- cmd = "makepatch --diff 'diff --text -u' --verbose"
- for glob in self.project.excludeFiles['always'] \
- + self.project.excludeFiles['patch'] \
- + self.project.excludeFiles['generated']:
- cmd += " --exclude '%s'" % glob
- cmd += " %s %s > %s" % (oldspace,newspace,patchkit)
- # FIXME: makepatch should generate the following output:
- # Processing the filelists ...
+ if self.download is not None:
+ download = formatNamedVariables (self.download, map)
+ else:
+ download = formatNamedVariables ("""\
+* Availability
+
+Anonymous ftp:
+
+
ftp://ftp.xemacs.org/pub/xemacs/xemacs-21.4
+
+See
http://www.xemacs.org/Install/. (Note that the tarball breakdown
+is slightly different from that implied for 21.1. For 21.4, the
+xemacs-%(version)s.tar.gz tarball contains the full contents of the
+xemacs-%(version)s-{src,elc,info}.tar.gz tarballs.)
+
+If you already have a %(previousVersion)s source tree, a patchkit is available in
+xemacs-%(previousVersion)s-%(version)s.patch.gz. This does not update .elcs or .infos,
+they will be rebuilt when you make XEmacs. If you have an earlier
+version, you can repeatedly apply patchkits.
+
+Also, if you do not have the packages yet, see
+
+
http://www.xemacs.org/Documentation/packageGuide.html.
+
+Windows branch and installers:
+
+The Windows branch continues to have a few changes not yet included in
+the mainline. It is preferred to the mainline for Windows users.
+
+Anonymous (pserver) CVS:
+
+Anonymous CVS is available. We are very grateful to the staff at our
+host, SunSITE.dk, for a lot of help and quick reponse to all our
+requests.
+
+If you haven't used XEmacs CVS recently, we moved the repository
+before the 21.4.6 release. The repository structure is the same as
+before, so it should be possible to reuse an existing checked-out CVS
+tree.
+
+Take care that your Root is set correctly to
+
+ CVSROOT=:pserver:cvs@cvs.xemacs.org:/pack/xemacscvs
+
+On platforms with a Bourne shell and find available, something like
+
+ for r in `find . -name Root`; do echo $CVSROOT > $r; done
+
+will convert your entire tree.
+
+Tags are also the same; to update to release %(version)s, use the release
+tag "%(releaseSpec)s". To update to the current release, use the flag
+"%(currentSpec)s". To update to the latest commits in CVS, use the flag
+"%(branchSpec)s".
+
+For more details, see
+
+
http://www.xemacs.org/Develop/cvsaccess.html
+
+Unique branch and release tags are assigned to the Windows branch.
+See Andy Piper's announcements and release notes for details.""",
map)
+
+ post = header + "\n\n\n" + intro + news + "\n\n" + \
+ blurb + "\n\n" + disclaimer + "\n\n" + download +
"\n\n\n"
+ html = preamble + post + postamble
+ post = substituteHTMLEntities (post, HTMLEntityDictionary)
+
+ self.parseChangesFile() # FIXME: this should only be done once
+ #self.sortChanges()
+ html += self.changesToHTML()
+ post += self.changesToText()
+
+ # FIXME: this header should be generated
+ # FIXME: ChangeLogs should be sorted
+ html += '''\
+ <h1><a name="changes">ChangeLogs</a> for XEmacs %s
"%s"</h1>
+ <p>goto <a href="#announcement">announcement</a>,
+ <a href="#summary">summary</a>,
+ changes</p>
+ <ul>
+ <li>ChangeLog Entries from <a
href="#ChangeLog">ChangeLog</a></li>
+''' % (self.versionString, self.codename)
+ v = self.version
+ if v[0] > 21 or v[0] == 21 and (v[1] > 5 or v[1] == 5 and v[2] > 15):
+ html += '''\
+ <li>ChangeLog Entries from <a
href="#etc:ChangeLog">etc/ChangeLog</a></li>
+'''
+ html += '''\
+ <li>ChangeLog Entries from <a
href="#lib-src:ChangeLog">lib-src/ChangeLog</a></li>
+ <li>ChangeLog Entries from <a
href="#lisp:ChangeLog">lisp/ChangeLog</a></li>
+ <li>ChangeLog Entries from <a
href="#lwlib:ChangeLog">lwlib/ChangeLog</a></li>
+ <li>ChangeLog Entries from <a
href="#man:ChangeLog">man/ChangeLog</a></li>
+ <li>ChangeLog Entries from <a
href="#netinstall:ChangeLog">netinstall/ChangeLog</a></li>
+ <li>ChangeLog Entries from <a
href="#nt:ChangeLog">nt/ChangeLog</a></li>
+ <li>ChangeLog Entries from <a
href="#src:ChangeLog">src/ChangeLog</a></li>
+ <li>ChangeLog Entries from <a
href="#tests:ChangeLog">tests/ChangeLog</a></li>
+ </ul>\n\n'''
+
+ for log in self.findChangeLogs ("."):
+ html += self.changeLogToHTML (log)
+ # FIXME: this header should be generated
+ # FIXME: ChangeLogs should be sorted
+ for log in self.findChangeLogs ("."):
+ post += self.changeLogToText (log)
+
+ html += '''\
+ <p>goto <a href="#announcement">announcement</a>,
+ <a href="#summary">summary</a>,
+ <a href="#changes">changes</a></p>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: xml
+sgml-omittag:nil
+sgml-shorttag:nil
+sgml-namecase-general:nil
+sgml-general-insert-case:lower
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:("../template.html" "html" "body"
"table" "tr" "td")
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->
+'''
+ post += """--
+Institute of Policy and Planning Sciences
http://turnbull.sk.tsukuba.ac.jp
+University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN
+ Ask not how you can "do" free software business;
+ ask what your business can "do for" free software.
+"""
+
+ stage = self.engineer.stage
+ f = open ("%s/%s.content" % (stage, self.versionString),
"w")
+ f.write (html)
+ f.close()
+ f = open ("%s/%s.announce" % (stage, self.versionString),
"w")
+ f.write (post)
+ f.close()
+
+
+ def abstract (self, flags=Flags({})):
+ """Extract and acquire documentation.
+ Extract brief change notices, full logs, and other info useful in
+ announcements. Collect them in an abstract in the staging directory.
+ Download current versions of READMEs etc available on the net.
+
+ Depends on `finalize' to determine codename."""
+
+ dryRun = flags.val('dryRun')
+ noNet = flags.val('noNet')
+ verbose = flags.val('verbose')
+
+ p = self.project
+ e = self.engineer
+
+ download = copy(p.download)
+ download.merge(e.download)
+
+ os.chdir(e.stage)
+
+ # Down and update FTP READMEs for public releases.
+ for filename in ['.message','README']:
+ localname = self.versionString+"."+filename
+
+ if os.access (localname, os.W_OK) or os.access (".", os.W_OK) \
+ and not os.access (localname, os.F_OK):
+ cmd = download.scp (source=filename, target=localname)
+ execAndTrace (cmd, dryRun + noNet, verbose)
+ else:
+ print "Couldn't update %s: not writable." % filename
+
+ # FIXME: global replace is not what we want here
+ if os.access (localname, os.R_OK):
+ f = open (localname)
+ old = f.read ()
+ f.close ()
+ new = replace (old, "%d.%d.%d" % self.previousVersion,
+ self.versionString)
+ f = open (localname, "w")
+ f.write (new)
+ f.close ()
+ else:
+ print "Couldn't update %s: not readable." % filename
+
+ herald_re = r'XEmacs.* (\d+)\.(\d+)(\.|-beta)(\d+).*is released'
+ changes_tag_re = r'^to( XEmacs)? (\d+)\.(\d+)\.(\d+) "(.+)"$'
+ os.chdir(e.stage + "/" + self.stem)
+
+ # handle change documentation
+ lines = []
+
+ # handle CHANGES-{beta,release}
+ if not self.changesEntries:
+ self.parseChangesFile()
+
+ lines.append('Brief summary of Changes to %s "%s"\n' \
+ % (self.versionString,self.codename))
+ for entry in self.changesEntries:
+ if entry[0] == 'section':
+ lines.append("\n%s\n\n" % entry[3])
+ elif entry[0] in [ 'new', 'fix', 'improve',
'update' ]:
+ # FIXME: fold long lines, see module textwrap
+ lines.append("-- %s: %s -- %s\n" \
+ % (entry[0].capitalize(), entry[3], entry[4]))
+ elif entry[0] == 'version':
+ # FIXME: warn here
+ pass
+ else:
+ # FIXME: warn here
+ pass
+
+ # handle ChangeLogs
+ for log in self.findChangeLogs ("."):
+ if verbose > 0:
+ print log
+ # consistent with Martin's format
+ lines.append("\n-------- ChangeLog entries from %s --------\n\n" \
+ % log)
+ f = open(log,"r")
+ line = f.readline()
+ while line:
+ if verbose > 1:
+ print line
+ # FIXME: maybe this should be less fuzzy
+ m = re.search(herald_re, line)
+ if (m and
+ (int(m.group(4)) != self.version[2] or
+ int(m.group(2)) != self.version[1] or
+ int(m.group(1)) != self.version[0])):
+ lines = lines[:-2]
+ break
+ else:
+ lines.append(line)
+ line = f.readline()
+ f.close()
+ f = open ("%s/%d.%d.%d-Abstract" % ((e.stage,) + self.version),
"w")
+ for line in lines:
+ f.write(line)
+ f.write("""\
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: xml
+sgml-omittag:nil
+sgml-shorttag:nil
+sgml-namecase-general:nil
+sgml-general-insert-case:lower
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:("../template.html" "html" "body"
"table" "tr" "td")
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->
+""")
+ f.close()
+
+
+ def package (self, flags=Flags({})):
+ """Create distribution ready for upload.
+
+ Distribution includes patch, tarball(s), and PGP signatures.
+
+ Flags observed are verbose, dontAsk, and dryRun."""
+
+ dryRun = flags.val('dryRun')
+ dontAsk = flags.val('dontAsk')
+ verbose = flags.val('verbose')
+
+ if dryRun and verbose:
+ print "Dry run, not making tarballs."
+ elif dontAsk and verbose:
+ print "Dry run, making tarballs but not signing."
+
+ # cd to staging directory
+ os.chdir(self.engineer.stage)
+
+ # make patch
+ # do it before making tarballs, which generates .elcs and .infos
+ newspace = self.stem
+ oldspace = self.previousStem
+ patchkit = self.previousStem + "-" + self.versionString +
".patch"
+
+ findcmd = "find . -name CVS -prune -or -type f -print > MANIFEST"
+
+ if verbose:
+ print "cd to " + self.previousStem
+ os.chdir(self.previousStem)
+ execAndTrace(findcmd, dryRun, verbose)
+
+ if verbose:
+ print "cd to ../" + self.stem
+ os.chdir("../" + self.stem)
+ execAndTrace(findcmd, dryRun, verbose)
+
+ os.chdir("..")
+
+ cmd = "makepatch --diff 'diff --text -u' --verbose"
+ for glob in self.project.excludeFiles['always'] \
+ + self.project.excludeFiles['patch'] \
+ + self.project.excludeFiles['generated']:
+ cmd += " --exclude '%s'" % glob
+ cmd += " %s %s > %s" % (oldspace,newspace,patchkit)
+ # FIXME: makepatch should generate the following output:
+ # Processing the filelists ...
# Collecting patches ...
# 167 files need to be patched.
# 2 files need to be created.
@@ -1050,6 +1474,7 @@ End:
# (for f in pars; do tar tf $f; done) | sort > union.manifest
# uniq -d union.manifest should be empty
# diff full.manifest union.manifest should be empty
+ # (#### Isn't this redundant against 4?)
# 6. ./configure --prefix=$staging/install; make; make check;
# make install
# 7. gzip -t *.gz
@@ -1080,7 +1505,7 @@ End:
tag = copy(p.cvsRW)
tag.merge(e.cvsRW)
- tag.query = "tag"
+ tag.query = "tag -F"
releaseTag = ("r%d-%d-%d" % self.version) + self.tagTail
rtag = copy(tag)
@@ -1097,16 +1522,11 @@ End:
self.warnings.append("""\
Commit changed files (ChangeLogs and version.sh, maybe CHANGES-beta or
CHANGES-release, configure, or src/depend) and tag Repository:
-1. mv configure configure.save; autoconf; if diff configure configure.save;
- then rm configure.save; cvs commit configure; else mv configure.save
- configure; fi (FIXME: unimplemented
- Should be able to do this with a cvs update after autoconf, or a
- cp and diff strategy (this is better, can do without net).)
-2. for file in changedFiles: # necessary because of
cvs.xemacs.org fuckage
+1. for file in changedFiles: # necessary because of
cvs.xemacs.org fuckage
%s
-3. cvs update, checking for any changes or modification
+2. cvs update, checking for any changes or modification
+3. %s
4. %s
-5. %s
Run the beta version of this function with
`release.tag(flags={'dryRun':0})'.
""" \
@@ -1177,8 +1597,14 @@ Run the beta version of this function wi
# paranoia re premature access
for f in uploadlist:
- if verbose > 0: print "chmod 0600 " + f
- os.chmod(f,0600)
+ if verbose > 0:
+ if dryRun:
+ print "DRYRUN>",
+ else:
+ print "XRE>",
+ print "chmod 0600", f
+ if not dryRun:
+ os.chmod(f,0600)
for cmd in [
shell.run("mkdir -p %s && cd %s && rm -f %s" \
@@ -1386,6 +1812,8 @@ Post to xemacs-beta (for betas and prere
def makeTarballs (self, dir, fullOnly=0, dryRun=-1, verbose=2):
"""Make distribution tarballs for XEmacs.
+ Depends on finalize to update configure and src/depend.
+
Always make the full source + compiled Lisp + Info tarball.
If fullOnly is false, also make the disaggregated source-only,
elc, and info tarballs."""
@@ -1393,15 +1821,6 @@ Post to xemacs-beta (for betas and prere
# prep
e = self.engineer
p = self.project
-
- # ensure configure is up to date
- if verbose:
- print "Updating configure: ",
- # NB: cvs will not commit unless it's different (according to diff)
- os.chdir(e.stage + "/" + self.stem)
- execAndTrace(self.engineer.autoconf)
- if verbose:
- print "done."
os.chdir(e.stage)
def makeTarball (tarball, arguments, verbose = 1):
@@ -1433,27 +1852,21 @@ Post to xemacs-beta (for betas and prere
# build and clean leaving .elcs and .infos
# FIXME: *must* check error returns!!
- # FIXME: all of these flags should be configured in Release and
- # Project objects ESPECIALLY WITH autobumpf 2.13/2.5x CONFLICT!!
- additionalConfigureFlags = " --enable-sound=none"
testXEmacsAuto = " && make check"
testXEmacsOnX = " && LC_ALL=C src/xemacs -vanilla" \
+ " -eval '(sleep-for 2)' -kill"
ret = execAndTrace("cd %s" % dir \
- + " && ./configure --enable-mule" \
- + " --enable-dialogs=athena" \
- + " --enable-widgets=athena" \
- + " --with-athena=xaw" \
- + " --enable-pdump" \
- + additionalConfigureFlags \
+ + " && mkdir +build && cd +build"
+ + " && ../configure " + self.configureFlags
\
+ " && make depend" \
+ " && make" \
+ testXEmacsAuto \
- + testXEmacsOnX \
- + " && make distclean")
- # FIXME: a broken make doesn't seem to return true
+ + testXEmacsOnX)
+ # FIXME: a broken make doesn't seem to return failure code
self.warnings.append("Error return (%s) from build!" % (ret.code))
+ # FIXME: this would be a good place to do a build report
+
# make full tarball
tarball = dir + ".tar"
targets = " " + dir
@@ -1495,7 +1908,7 @@ Post to xemacs-beta (for betas and prere
# define and initialize a Filter
def filterFunction (line, filter):
- m = match(filter.regexp,line)
+ m = re.match(filter.regexp,line)
if m:
filter.matchCount += 1
filter.text += "%s%d%s\n" % (m.group(1),
@@ -1562,7 +1975,7 @@ Post to xemacs-beta (for betas and prere
codename = strip(lines[versionTuple[2]])
else:
for line in file.readlines():
- m = match(versionString + ":\s*(\S.*)$",line)
+ m = re.match(versionString + ":\s*(\S.*)$",line)
if m:
codename = strip(m.group(1))
file.close()
@@ -1574,6 +1987,7 @@ Post to xemacs-beta (for betas and prere
## version.sh handling
+ # FIXME: the hardcoding of the shebang is bogus
def parseVersionFile (self, dryRun=0, verbose=0):
"""Parse version.sh into the versionDictionary member.
@@ -1581,7 +1995,11 @@ Post to xemacs-beta (for betas and prere
is raised. Empty lines and comments are ignored (and not entered in
the dictionary). Fields must be unique or an error is raised.
- Unknown fields are added to the versionRogueFields member."""
+ The contents of the version file are defined by the
+ versionStandardFields and versionRequiredFields of the Release
+ object. The parsing process fills the Release object's
+ versionDictionary with (field, value) pairs, and unknown fields are
+ added to the versionRogueFields member."""
self.versionDictionary = {}
for field in self.versionStandardFields:
@@ -1594,8 +2012,8 @@ Post to xemacs-beta (for betas and prere
self.versionDictionary['shebang'] = strip(file.readline())
for line in file.readlines():
- if match(r"^(\s*|\s*#.*)$", line): continue
- m = match(r"^([^=]+)=(.*)$", line)
+ if re.match(r"^(\s*|\s*#.*)$", line): continue
+ m = re.match(r"^([^=]+)=(.*)$", line)
if not m: raise Error
key = strip(m.group(1))
value = strip(m.group(2))
@@ -1613,15 +2031,18 @@ Post to xemacs-beta (for betas and prere
# FIXME this isn't really "validation"
def validateVersionDictionary (self, dryRun=0, verbose=0):
"""Validate the version dictionary.
+ Returns 0 if version successfully updated, 1 if already updated,
+ and 2 for errors.
If the beta version is the previous value, update it.
Requires that the version and codename members be initialized."""
+ result = 0
for key, value in self.versionDictionary.items():
- if key == 'shebang' and not match(r"^#!", value):
+ if key == 'shebang' and not re.match(r"^#!", value):
raise Error
- elif key == 'emacs_is_beta' and not match(r"^t?$", value):
+ elif key == 'emacs_is_beta' and not re.match(r"^t?$",
value):
self.warnings.append('strange emacs_is_beta value: ' + value)
elif key == 'emacs_major_version':
if self.version[0] == int(value):
@@ -1646,12 +2067,13 @@ Post to xemacs-beta (for betas and prere
self.warnings.append('bumped emacs_beta_version')
elif self.version[2] == int(value):
self.warnings.append('version.sh is already finalized?')
+ result = 1
else:
raise Error
elif key == 'xemacs_codename':
codename_re = "['\"]?%s" % (self.codename, )
# FIXME: should this be a re.search, instead?
- if not match(codename_re, value):
+ if not re.match(codename_re, value):
self.versionDictionary[key] = '"%s"' %
(self.codename, )
self.warnings.append('codename updated to current')
elif key == 'xemacs_extra_name':
@@ -1673,7 +2095,9 @@ Post to xemacs-beta (for betas and prere
warning += field + ", "
self.warnings.append(warning[:-2])
+ return result
+
def writeVersionFile (self, dryRun=0, verbose=0):
"""Write version.sh based on the versionDictionary
member."""
@@ -1705,130 +2129,137 @@ Post to xemacs-beta (for betas and prere
## CHANGES file handling
def parseChangesFile (self, dryRun=0, verbose=0):
- """Return a list of (type, section, platform, item, name) tuples.
+ """Parse a list of (type, section, platform, item, name) tuples.
+
+ This function must be run in the directory containing the file.
+
+ The list is placed in the changesEntries attribute of the Release
+ object. The boolean attribute versionMarkerFound is set True if
+ and only if the current version was found.
Only items up to the next version marker are returned.
- The raw CHANGES file basically consists of change items, which are
- full lines matching r'( *)-- (.*) -- (.*)' where the second group
- is the descriptive text, and the third group is the contributor
- name(s).
-
- The section is parsed from elsewhere. Typical sections are UI,
- Lisp API, internals, doc, etc.
-
- The other defined kind of entry is a version marker, a full line
- matching r'to( XEmacs)? (\d+)\.(\d+)\.(\d+) "(.+)"'.
-
- Optionally, there may be prefatory material which continues up to
- the first change item or version marker, which is ignored. Any
- other text not matching the defined entries will generate a
- warning or error."""
+ The parser is line-oriented. Lines containing only whitespace
+ serve to terminate the current logical line and are otherwise
+ ignored. A logical line has non-whitespace in column 1. Anything
+ else is a continuation of the current logical line. The terminating
+ newline is stripped, leading whitespace is compressed to a single
+ and the result is appended to the current logical line.
+
+ Version markers match r'to( XEmacs)? (\d+)\.(\d+)\.(\d+)
"(.+)"'.
+ A version marker may not be folded.
+
+ Change items match r'-- (.*) -- (.*)' where the second group is the
+ descriptive text, and the third group is the contributor name(s).
+
+ A section head is any non-empty line not matching the above.
+ Currently used sections are 'Major Features', 'User-Visible Bug
+ Fixes and Minor Improvements', 'Build Infrastructure',
+ 'Documentation', 'Lisp API', and 'Internal API and
Implementation'.
+
+ An item's type is 'version' (marker), 'section' (head), or an
item,
+ with type 'new' (feature), 'improve' (feature), 'fix' (a
bug), or
+ 'update' (semantics unclear). Type is currently parsed when the
+ first word of the text matches the type name. The type keyword,
+ separating whitespace and punctuation (usually a colon) are removed
+ from the text.
+
+ Platform is not currently used. Platform could be parsed by keyword
+ matching against the item text.
+
+ Optionally, there may be prefatory material (parsed as a series of
+ empty sections followed by a change item---creating a non-empty
+ section---or a version marker), which is ignored. Any other text
+ not matching the defined entries will generate a warning or
error."""
+
+ if not os.access (self.changesFile, os.R_OK):
+ # FIXME: do something more useful here
+ raise IOError, "No CHANGES file found."
+ elif verbose:
+ print "XRE> Parsing %s in %s." %
(self.changesFile,os.getcwd())
# #### Maybe these variables should move to a config object?
- kindRE = r'(fix|update|new|improve)'
- sectionRE = r'(UI|Lisp API|internal|doc)'
- platformRE = r'(Unix|(native )?Windows|Cygwin|GTK|Motif|Qt)'
- itemRE = r'^-- '
- versionMarkerRE = r'to( XEmacs)? (\d+)\.(\d+)\.(\d+)
"([^"]+)"'
- entryRE = "%s|%s" % (itemRE, versionMarkerRE)
-
+ versionMarkerRE = re.compile(r'to (?:XEmacs )?(\d+)\.(\d+)\.(\d+)'
+ + r'\s+("([^"]+)")?',
re.IGNORECASE)
+ # old: sectionRE = r'(UI|Lisp API|internal|doc)'
+ itemRE = re.compile(r'--\s+(.*)\s+(?:-- (\S(?:.*\S)))?$')
+ kindRE = re.compile(r'(fix|update|new|improve):?\s+',re.IGNORECASE)
+ platformRE = re.compile(r'\b(Unix|(?:native )?Windows(?: NT)?|Cygwin'
+ + r'|GTK|Motif|Qt)\b', re.IGNORECASE)
+ # old: entryRE = "%s|%s" % (itemRE, versionMarkerRE)
+
+ # FIXME: where should we validate thisVersionMarkerFound?
+ self.thisVersionMarkerFound = False
+ version = None
+ section = None
+ continuation = None
self.changesEntries = []
- versionMarkerFound = 0
f = open(self.changesFile,"r")
- if not f:
- raise FileError, "No CHANGES file."
-
- line = f.readline ()
- m = match (entryRE, line)
- if not m and verbose:
- print "Found prefatory material. Skipping...."
- while line:
- if match (entryRE, line):
+ # FIXME: this is bogus, probably should be a try
+ #if not f:
+ # raise FileError, "No CHANGES file."
+
+ while True:
+ if continuation:
+ line = continuation
+ continuation = None
+ else:
+ # heuristic: strip first physical line of new logical line
+ line = f.readline().strip()
+ if not line:
break
if verbose > 1:
- print strip(line)
- line = f.readline ()
-
- m = match (versionMarkerRE, line)
- if m:
- if verbose:
- print "Found initial version marker."
- ver = (int(m.group(2)), int(m.group(3)), int(m.group(4)))
- codename = m.group(5)
- if ver == self.version:
- if not match(codename, self.codename):
- self.warnings.append("codename differs in %s" \
- % self.changesFile)
- else:
- raise ValueError, \
- "%s not up to date (expected %s, found %s)" \
- % (self.changesFile, self.version, ver)
- line = f.readline()
-
- while line:
- m = match (itemRE, line)
- if m:
- line = strip (line)
- if verbose:
- print "Found an item."
- while 1:
- more = f.readline()
- if more and match (r"\s+\S", more):
- line += " " + strip (more)
- else:
- break
- developer = line
- descriptionEnd = 0
- while 1:
- m = search (" -- ", developer)
- if m:
- descriptionEnd += m.start(0)
- developer = developer[m.end(0):]
- else:
- break
- if descriptionEnd:
- description = line[3:descriptionEnd]
- else:
- self.warnings.append ("no developer in %s item:\n %s" \
- % (self.changesFile, line))
- developer = ""
- description = line[3:]
- kind = search (kindRE, description)
- if kind:
- kind = kind.group(0)
- else:
- kind = ""
- section = search (sectionRE, description)
- if section:
- section = section.group(0)
- else:
- section = ""
- platform = search (platformRE, description)
- if platform:
- platform = platform.group(0)
- else:
- platform = ""
- self.changesEntries.append((kind, section, platform,
- description, developer))
- line = more
- continue
- m = match (versionMarkerRE, line)
- if m:
- if verbose:
- print "Found terminating version marker."
- ver = (int(m.group(2)), int(m.group(3)), int(m.group(4)))
- if ver == self.previousVersion:
+ print line
+ m0 = versionMarkerRE.match(line)
+ if m0:
+ # no folding permitted
+ version = (int(m0.group(1)),int(m0.group(2)),int(m0.group(3)))
+ codename = m0.group(4)
+ if version == self.version:
+ self.thisVersionMarkerFound = True
+ if verbose:
+ print "Found current version marker."
+ if not re.match(codename, self.codename):
+ self.warnings.append("codename differs in %s" \
+ % self.changesFile)
+ # FIXME: this is probably self.previousVersion
+ elif version[0:2] == self.version[0:2] \
+ and version[2] == self.version[2] - 1:
+ if verbose:
+ print "Found previous version marker."
break
else:
- raise ValueError, "incorrect version marker in %s" \
- % self.changesFile
- elif not match (r"^\s*$", line):
- self.warnings.append ("unparsable line in %s:\n %s" \
- % (self.changesFile, line))
- line = f.readline ()
-
+ raise ValueError, \
+ "%s not up to date (expected %s, found %s)" \
+ % (self.changesFile, self.version, version)
+ else:
+ while True:
+ more = f.readline()
+ if more and re.match (r"\s+\S", more):
+ line += " " + strip (more)
+ else:
+ continuation = strip(more)
+ break
+ m1 = itemRE.match(line)
+ if m1:
+ if verbose:
+ print "Found an item."
+ text = m1.group(1)
+ developer = m1.group(2)
+ kind = kindRE.match(text)
+ if kind:
+ text = text[kind.end(0):]
+ kind = kind.group(1).lower()
+ platform = re.search (platformRE, text)
+ if platform:
+ platform = platform.group(0)
+ self.changesEntries.append((kind,section,platform,
+ text,developer))
+ elif line:
+ section = line
+ self.changesEntries.append(('section',section,None,
+ section,None))
def sortChanges (self, dryRun=0, verbose=0):
@@ -1877,22 +2308,42 @@ Post to xemacs-beta (for betas and prere
Current implementation does not handle lists of related changes
by a single developer."""
- html = """\
- <h1><a name="summary">Changes</a> in XEmacs %s
"%s"</h1>
- <p>goto <a href="#announcement">announcement</a>,
summary,
- <a href="#changes">changes</a></p>
- <ul>
-""" % (self.versionString, self.codename)
+ # Use triple single quotes to keep Python mode from parsing
+ # URL fragments as python comments.
+ html = '''\
+ <h1><a name="summary">Changes</a> in XEmacs %s
"%s"</h1>
+ <p>goto <a href="#announcement">announcement</a>,
summary,
+ <a href="#changes">changes</a></p>
+''' % (self.versionString, self.codename)
+ list_is_open = False
for e in self.changesEntries:
- html += """\
- <li>
- %s (<em>%s</em>)
- </li>
-""" % (escape(e[3], htmlEscapeDictionary),
- escape(e[4], htmlEscapeDictionary))
-
- return html + " </ul>\n\n"
+ print e[0], e[3], e[4]
+ if e[0] == 'section':
+ if list_is_open:
+ list_is_open = False
+ html += '''
+ </ul>
+'''
+ html += '''
+ <h2>%s</h2>
+''' % (escape(e[3], htmlEscapeDictionary),)
+ elif e[0] in [ 'new', 'fix', 'improve',
'update' ]:
+ if not list_is_open:
+ list_is_open = True
+ html += '''
+ <ul>
+'''
+ html += """\
+ <li>
+ %s: %s (<em>%s</em>)
+ </li>
+""" % (escape(e[0].capitalize(), htmlEscapeDictionary),
+ escape(e[3], htmlEscapeDictionary),
+ escape(e[4], htmlEscapeDictionary))
+ if list_is_open:
+ html += " </ul>\n"
+ return html + "\n"
def changesToText (self, dryRun=0, verbose=0):
@@ -1904,13 +2355,17 @@ Post to xemacs-beta (for betas and prere
Current implementation does not handle lists of related changes
by a single developer."""
- text = '* Brief summary of Changes to XEmacs %s "%s"\n\n' \
+ text = '* Brief summary of Changes to XEmacs %s "%s"' \
% (self.versionString, self.codename)
for e in self.changesEntries:
- text += "-- %s -- %s\n" % (e[3], e[4])
+ if e[0] == 'section':
+ text += "\n\n%s\n" % (e[3],)
+ elif e[0] in [ 'new', 'fix', 'improve',
'update' ]:
+ text += "\n-- %s: %s -- %s" \
+ % (e[0].capitalize(), e[3], e[4])
- return text + "\n"
+ return text + "\n\n"
## ChangeLog handling
@@ -1943,7 +2398,7 @@ Post to xemacs-beta (for betas and prere
os.chdir(dir)
def clean (string):
- if match ("./", string):
+ if re.match ("./", string):
string = string[2:]
if string[-1] == "\n":
string = string[:-1]
@@ -1981,6 +2436,9 @@ Post to xemacs-beta (for betas and prere
if not herald: herald = self.herald
if not engineer: engineer = self.engineer
+ if verbose:
+ print "Processing ", log, " ...",
+
infile = open(log, "r")
contents = infile.read()
infile.close
@@ -1988,10 +2446,10 @@ Post to xemacs-beta (for betas and prere
#### FIXME definitions duplicated in abstractChangeLog
logRE = r'\d\d\d\d-\d\d-\d\d .* <[^>]*>'
heraldRE = r'XEmacs.* (\d+)\.(\d+)(\.|-beta)(\d+).*is released'
- releaseRE = compile(logRE + r'\n\n\t\* .*' \
- + heraldRE + r'.*\n\n')
+ releaseRE = re.compile(logRE + r'\n\n\t\* .*' \
+ + heraldRE + r'.*\n\n')
- m = search(releaseRE, contents)
+ m = releaseRE.search(contents)
if not m:
raise ValueError, "%s contains no herald" % log
elif self.version == tuple(map(int, (m.group(1,2,4)))):
@@ -2029,8 +2487,7 @@ Post to xemacs-beta (for betas and prere
logRE = r'\d\d\d\d-\d\d-\d\d .* <[^>]*>'
heraldRE = r'XEmacs.* (\d+)\.(\d+)(\.|-beta)(\d+).*is released'
- releaseRE = compile(logRE + r'\n\n\t\* .*' \
- + heraldRE + r'.*\n\n')
+ releaseRE = re.compile(logRE + r'\n\n\t\* .*' + heraldRE +
r'.*\n\n')
f = open(log,"r")
text = f.read()
@@ -2088,14 +2545,14 @@ Post to xemacs-beta (for betas and prere
contents = self.abstractChangeLog (changelog)
- template = """\
+ template = '''\
<h2>ChangeLog Entries from <a
name="%s">%s</a></h2>
<p>goto <a href="#announcement">announcement</a>,
<a href="#summary">summary</a>,
<a href="#changes">changes</a></p>
<pre xml:space="preserve">
-"""
+'''
html = template % (anchor, changelog)
html += strip(escape(contents, htmlEscapeDictionary))
return html + "</pre>\n\n"
@@ -2116,277 +2573,6 @@ Post to xemacs-beta (for betas and prere
+ strip(contents) + "\n\n"
- def writeAnnouncements (self):
- """Write #.#.#.content and #.#.#.announce files in the staging
- directory.
-
- Requires codename and herald to be previously generated."""
-
- map = {}
- if self.announceAddress:
- map['announceAddress'] = self.announceAddress
- else:
- map['announceAddress'] = 'xemacs-announce(a)xemacs.org'
- map['herald'] = self.herald[:-1] # strip the period
- #### These probably have ...String versions.
- map['version'] = "%d.%d.%d" % self.version
- map['previousVersion'] = "%d.%d.%d" % self.previousVersion
- map['codename'] = self.codename
- map['previousCodename'] = self.getCodenameFromFile
(self.previousVersion)
- map['series'] = self.getSeriesFromCodenameFilename ()
- if self.reliability:
- map['reliability'] = self.reliability
- else:
- map['reliability'] = 'beta'
- map['engineer'] = self.engineer.fullName
- map['role'] = self.engineer.comment
- map['alias'] = self.engineer.projectAlias
- map['domain'] = self.project.mailDomain
- #### This won't work for 21.4!
- map['releaseSpec'] = "-r r%d-%d-%d" % self.version
- map['currentSpec'] = "-r r%d-%d-current-beta" %
self.version[:2]
- map['branchSpec'] = "-A"
- ordinals = [ 'first', 'second', 'third',
'fourth', 'fifth', 'sixth', \
- 'seventh', 'eighth', 'ninth',
'tenth', 'eleventh', \
- 'twelfth', 'thirteenth', 'fourteenth',
'fifteenth', \
- 'sixteenth', 'seventeenth', 'eighteenth',
'nineteenth', \
- 'twentieth', 'twenty-first',
'twenty-second',
- 'twenty-third', 'twenty-fourth',
'twenty-fifth',
- 'twenty-sixth', 'twenty-seventh',
'twenty-eighth',
- 'twenty-ninth', 'thirtieth' ]
- map['ordinal'] = ordinals[self.version[2]]
-
- # genpage wrapper
- # **** You probably should NOT replace these. ****
- if self.postamble is not None:
- postamble = self.postamble
- else:
- postamble = """</pre>\n\n"""
- if self.preamble is not None:
- preamble = self.preamble
- else:
- preamble = formatNamedVariables ("""\
-%title%
-%(herald)s
-%author%
-automatically generated (with release announcement) by xre.py
-%main%
- <h1><a
name="announcement">%(herald)s</a></h1>
- <p>goto announcement,
- <a href="#summary">summary</a>,
- <a href="#changes">changes</a></p>
- <pre xml:space="preserve">
-""", map)
-
- # **** You usually shouldn't need to replace this. ****
- if self.header is not None:
- header = formatNamedVariables (self.header, map)
- else:
- header = formatNamedVariables ("""\
-To: %(announceAddress)s
-From: "%(engineer)s, %(role)s" <%(alias)s@%(domain)s>
-Subject: %(herald)s.
-Organization: The XEmacs Project
-""", map)
-
- if self.intro is not None:
- intro = formatNamedVariables (self.intro, map)
- else:
- intro = formatNamedVariables ("""\
-* %(herald)s.
- "%(codename)s" is the %(ordinal)s in the %(series)s series.
-
-
-The successor to XEmacs %(previousVersion)s "%(previousCodename)s",\
- "%(codename)s" adds """, map)
-
- if self.news is not None:
- news = formatNamedVariables (self.news, map)
- else:
- news = "<INSERT NEWS HERE>"
-
- if self.blurb is not None:
- blurb = formatNamedVariables (self.blurb, map)
- else:
- blurb = """\
-The first release in this series, XEmacs 21.4.0 "Solid Vapor",
-contained a large number of improvements and extensions to the current
-stable version, XEmacs 21.1.14. For more information about the
-OXYMORON series, see etc/NEWS, the initial release announcement
-
-
http://www.xemacs.org/Releases/21.4.0.html
-
-and the release planning page,
-
-
http://www.xemacs.org/Releases/Public-21.2/
-
-For general information about XEmacs, the developers, and the user
-community, see our home page,
-
-
http://www.xemacs.org/"""
-
- if self.disclaimer is not None:
- disclaimer = formatNamedVariables (self.disclaimer, map)
- else:
- disclaimer = formatNamedVariables ("""\
-* XEmacs %(version)s is "%(reliability)s" software.
-
-The usual "no warranty" disclaimer (see etc/WARRANTY, sections 10 and
-11) applies. However, we are now experimenting with a level of
-stability intermediate between "beta" and "stable", dubbed
"gamma".
-At this point all the developers and our beta testers trust the 21.4
-code base with all their editing needs. Many have found it
-sufficiently stable that they've moved on to the development branch
-again in search of some excitement.
-
-After several months of testing, XEmacs %(version)s has been shown
-sufficiently stable to be recommended to all users. However, there
-still remain a few outstanding problems that must be fixed before we
-retire 21.1.""", map)
-
- if self.download is not None:
- download = formatNamedVariables (self.download, map)
- else:
- download = formatNamedVariables ("""\
-* Availability
-
-Anonymous ftp:
-
-
ftp://ftp.xemacs.org/pub/xemacs/xemacs-21.4
-
-See
http://www.xemacs.org/Install/. (Note that the tarball breakdown
-is slightly different from that implied for 21.1. For 21.4, the
-xemacs-%(version)s.tar.gz tarball contains the full contents of the
-xemacs-%(version)s-{src,elc,info}.tar.gz tarballs.)
-
-If you already have a %(previousVersion)s source tree, a patchkit is available in
-xemacs-%(previousVersion)s-%(version)s.patch.gz. This does not update .elcs or .infos,
-they will be rebuilt when you make XEmacs. If you have an earlier
-version, you can repeatedly apply patchkits.
-
-Also, if you don't have the packages yet, see
-
-
http://www.xemacs.org/Documentation/packageGuide.html.
-
-Windows branch and installers:
-
-The Windows branch continues to have a few changes not yet included in
-the mainline. It is preferred to the mainline for Windows users.
-
-Anonymous (pserver) CVS:
-
-Anonymous CVS is available. We are very grateful to the staff at our
-host, SunSITE.dk, for a lot of help and quick reponse to all our
-requests.
-
-If you haven't used XEmacs CVS recently, we moved the repository
-before the 21.4.6 release. The repository structure is the same as
-before, so it should be possible to reuse an existing checked-out CVS
-tree.
-
-Take care that your Root is set correctly to
-
- CVSROOT=:pserver:cvs@cvs.xemacs.org:/pack/xemacscvs
-
-On platforms with a Bourne shell and find available, something like
-
- for r in `find . -name Root`; do echo $CVSROOT > $r; done
-
-will convert your entire tree.
-
-Tags are also the same; to update to release %(version)s, use the release
-tag "%(releaseSpec)s". To update to the current release, use the flag
-"%(currentSpec)s". To update to the latest commits in CVS, use the flag
-"%(branchSpec)s".
-
-For more details, see
-
-
http://www.xemacs.org/Develop/cvsaccess.html
-
-Unique branch and release tags are assigned to the Windows branch.
-See Andy Piper's announcements and release notes for details.""",
map)
-
- post = header + "\n\n\n" + intro + news + "\n\n" + \
- blurb + "\n\n" + disclaimer + "\n\n" + download +
"\n\n\n"
- html = preamble + post + postamble
- post = substituteHTMLEntities (post, HTMLEntityDictionary)
-
- self.parseChangesFile() # FIXME: this should only be done once
- #self.sortChanges()
- html += self.changesToHTML()
- post += self.changesToText()
-
- # FIXME: this header should be generated
- # FIXME: ChangeLogs should be sorted
- html += """\
- <h1><a name="changes">ChangeLogs</a> for XEmacs %s
"%s"</h1>
- <p>goto <a href="#announcement">announcement</a>,
- <a href="#summary">summary</a>,
- changes</p>
- <ul>
- <li>ChangeLog Entries from <a
href="#ChangeLog">ChangeLog</a></li>
-""" % (self.versionString, self.codename)
- v = self.version
- if v[0] > 21 or v[0] == 21 and (v[1] > 5 or v[1] == 5 and v[2] > 15):
- html += """\
- <li>ChangeLog Entries from <a
href="#etc:ChangeLog">etc/ChangeLog</a></li>
-"""
- html += """\
- <li>ChangeLog Entries from <a
href="#lib-src:ChangeLog">lib-src/ChangeLog</a></li>
- <li>ChangeLog Entries from <a
href="#lisp:ChangeLog">lisp/ChangeLog</a></li>
- <li>ChangeLog Entries from <a
href="#lwlib:ChangeLog">lwlib/ChangeLog</a></li>
- <li>ChangeLog Entries from <a
href="#man:ChangeLog">man/ChangeLog</a></li>
- <li>ChangeLog Entries from <a
href="#netinstall:ChangeLog">netinstall/ChangeLog</a></li>
- <li>ChangeLog Entries from <a
href="#nt:ChangeLog">nt/ChangeLog</a></li>
- <li>ChangeLog Entries from <a
href="#src:ChangeLog">src/ChangeLog</a></li>
- <li>ChangeLog Entries from <a
href="#tests:ChangeLog">tests/ChangeLog</a></li>
- </ul>\n\n"""
-
- for log in self.findChangeLogs ("."):
- html += self.changeLogToHTML (log)
- # FIXME: this header should be generated
- # FIXME: ChangeLogs should be sorted
- for log in self.findChangeLogs ("."):
- post += self.changeLogToText (log)
-
- html += """\
- <p>goto <a href="#announcement">announcement</a>,
- <a href="#summary">summary</a>,
- <a href="#changes">changes</a></p>
-
-<!-- Keep this comment at the end of the file
-Local variables:
-mode: xml
-sgml-omittag:nil
-sgml-shorttag:nil
-sgml-namecase-general:nil
-sgml-general-insert-case:lower
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:2
-sgml-indent-data:t
-sgml-parent-document:("../template.html" "html" "body"
"table" "tr" "td")
-sgml-exposed-tags:nil
-sgml-local-catalogs:nil
-sgml-local-ecat-files:nil
-End:
--->
-"""
- post += """--
-Institute of Policy and Planning Sciences
http://turnbull.sk.tsukuba.ac.jp
-University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN
- Ask not how you can "do" free software business;
- ask what your business can "do for" free software.
-"""
-
- stage = self.engineer.stage
- f = open ("%s/%s.content" % (stage, self.versionString),
"w")
- f.write (html)
- f.close()
- f = open ("%s/%s.announce" % (stage, self.versionString),
"w")
- f.write (post)
- f.close()
-
### Where to get and update source code
class ServerURL:
@@ -2414,7 +2600,7 @@ class ServerURL:
def __init__ (self, url):
if url:
self.url = url
- m = match ("^([-_A-Za-z0-9]+)://" + \
+ m = re.match ("^([-_A-Za-z0-9]+)://" + \
"(([-_A-Za-z0-9.]+)(:([-_A-Za-z0-9.]+))?@)?" + \
"([-_A-Za-z0-9.]+)(/[^\?\#]*)" + \
"(\#[^?]*)?(\?.*)?$", url)
@@ -2740,9 +2926,9 @@ def updateCarefully (command, dryRun=0,
def updateCarefullyFilter (line, filter):
#### Is this OK? ACMR => commit needed, right?
- if match("[UP] ",line):
+ if re.match("[UP] ",line):
filter.code = 1
- if match("[ACMR] ",line):
+ if re.match("[ACMR] ",line):
filter.updateCarefullyInconsistencies.append(line)
filter.code = 1
return filter
@@ -2775,7 +2961,7 @@ def commitCarefully (command, dryRun=0,
Filter object returned."""
def commitCarefullyFilter (line, filter):
- if match("Checking in ", line):
+ if re.match("Checking in ", line):
filter.code = 1
filter.commitCarefullyCommits.append(line)
return filter
1.4 +17 -12 XEmacs/xemacs-builds/stephen/xre.texi
Index: xre.texi
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs-builds/stephen/xre.texi,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -p -r1.3 -r1.4
--- xre.texi 2003/09/05 07:36:23 1.3
+++ xre.texi 2006/02/25 13:39:16 1.4
@@ -31,7 +31,7 @@
@finalout
@titlepage
@title XEmacs Release Engineering
-@subtitle Manual for Release Engineers @* Last Modified: $Date: 2003/09/05 07:36:23 $
+@subtitle Manual for Release Engineers @* Last Modified: $Date: 2006/02/25 13:39:16 $
@sp 1
@author Stephen J. Turnbull <stephen(a)xemacs.org>
@page
@@ -41,8 +41,8 @@
@c If you know anything about any of the scripts in the xemacs-builds
@c module, please add a description to this file. If you have opinions
@c about procedure or policy in general, go ahead and add them. Release
-@c procedures are ultimately the property of the release engineer, but
-@c this file is not my property.
+@c procedures are ultimately the property of the incumbent release
+@c engineer, but this file is no single developer's property.
@ifinfo
@dircategory XEmacs Editor
@@ -152,7 +152,8 @@ than ChangeLog entries.
Create a complete source tree, free of cruft. This includes updating
generated files that for one reason or another are not automatically
updated. In particular, dependency files (make depend) and the
-configure script (autoconf, v 2.13 is required) must be updated.
+configure script (autoconf, at the time of writing v 2.13 is required
+although some important users---SuSE---are requesting v 2.5x) must be updated.
Although there should be no ``real'' changes to be logged, to help
readers establish a time line, a herald stating the date, release
engineer, and the version information for the release should be added to
@@ -248,15 +249,15 @@ responsibility @emph{ex oficio}.
For patch or beta releases, the release engineer updates the
appropriate @file{CHANGES} file. The @file{CHANGES} file notes
semantic aspects of the changes, rather than be a list of textual
-edits. (That's what @file{ChangeLogs} are for.) It is
+edits. (That's what @file{ChangeLogs} are for.) One must be
especially careful to give prominent notice of user interface changes,
including unobvious changes to command semantics. Every contributor
with a @file{ChangeLog} entry should be mentioned here.
@item configure
The configure script is updated by running @file{autoconf}. Note
-that as of January 2003, XEmacs @emph{requires} autoconf 2.13; later
-versions @emph{will not produce a correct configure script}.
+that as of March 2004, XEmacs @emph{requires} autoconf 2.13; later
+or earlier versions @emph{will not produce a correct configure script}.
@item src/depends
The dependency graph for the src subdirectory is updated by using the
@@ -304,8 +305,8 @@ build are included. These are the compi
generated Info files.
The component suite consists of the tarballs
-@file{xemacs-(a)var{version}-src.tar.gz}
-@file{xemacs-(a)var{version}-elc.tar.gz}
+@file{xemacs-(a)var{version}-src.tar.gz},
+@file{xemacs-(a)var{version}-elc.tar.gz}, and
@file{xemacs-(a)var{version}-info.tar.gz}, with the obvious contents.
These are not generated for beta test releases.
@@ -317,7 +318,8 @@ the previous patch release. The patch f
files, CVS administrative files, and the generated compiled Lisp and
Info files are excluded from the patch.
-The utility @file{makepatch} is very useful.
+The utility @file{makepatch} (a Perl script) is the usual way to create
+a patch.
@section Signing the Distribution
@@ -436,8 +438,11 @@ don't do operations requiring operator r
@end table
Every Python object has a Boolean value. The canonical idioms are 0
-(false) and 1 (true). A typical construction of a @samp{Flags} object,
-with assignment to a variable, might use a dictionary as
+(false) and 1 (true). (In Python 2.3, the canonical idioms were change
+to the special Boolean objects @code{True} and @code{False}, but the use
+of 0 and 1 persist in the @file{xre.py} code.) A typical construction
+of a @samp{Flags} object, with assignment to a variable, might use a
+dictionary as
@example
flags = @{ 'verbose': 1, 'dryRun': 1, 'bogusArg': "random
noise" @}
1.6 +20 -6 XEmacs/xemacs-builds/stephen/xre_data.py
Index: xre_data.py
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs-builds/stephen/xre_data.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -p -r1.5 -r1.6
--- xre_data.py 2005/09/15 03:14:08 1.5
+++ xre_data.py 2006/02/25 13:39:16 1.6
@@ -76,7 +76,7 @@ steve = Developer (
comment = "XEmacs 21.5 Beta Engineer",
projectAlias = "stephen",
mailingAddress = "turnbull(a)sk.tsukuba.ac.jp",
- stage = "/home/stephen/Projects/XEmacs/Releases/staging",
+ stage = "/Users/steve/Software/XEmacs/staging",
autoconf = "autoconf",
# Project resource accesses
cvsRW = Access (), # defaults
@@ -128,8 +128,15 @@ beta = Release(
codenameFile = "etc/VEGETABLES",
project = xemacs,
engineer = steve,
- cvsTag = None,
+ tipCVSTag = None,
# copySource = "/home/steve/Projects/XEmacs/xemacs-21.5",
+ configureFlags = "--enable-sound=none" \
+ + " --with-ldap=no" \
+ + " --enable-mule" \
+ + " --enable-dialogs=athena" \
+ + " --enable-widgets=athena" \
+ + " --with-athena=xaw" \
+ + " --enable-pdump",
# the order of the first few fields is built into M-x build-report
versionStandardFields = (
"shebang", "emacs_is_beta", "emacs_major_version",
@@ -222,7 +229,7 @@ gamma = Release(
ancestorVersion = (21,2,47),
codenameFile = "etc/OXYMORONS",
project = xemacs,
- cvsTag = "release-21-4",
+ tipCVSTag = "release-21-4",
# copySource = "/home/steve/Projects/XEmacs/21.4-HEAD",
engineer = steve,
versionStandardFields = (
@@ -234,7 +241,14 @@ gamma = Release(
versionRequiredFields = (
"shebang", "emacs_is_beta", "emacs_major_version",
"emacs_minor_version", "emacs_beta_version",
'xemacs_codename'
- )
+ ),
+ configureFlags = "--with-sound=none" \
+ + " --with-ldap=no" \
+ + " --with-mule" \
+ + " --with-dialogs=athena" \
+ + " --with-widgets=athena" \
+ + " --with-athena=xaw" \
+ + " --pdump",
)
@@ -242,7 +256,7 @@ candidate = copy(gamma)
candidate.isBeta = 1
# shouldn't need this
# candidate.changesFile = "CHANGES-release"
-candidate.cvsTag = "candidate-21-4"
+candidate.tipCVSTag = "candidate-21-4"
test = copy(beta)
@@ -250,7 +264,7 @@ test.engineer = tester
windows = copy(gamma)
-windows.cvsTag = "windows-21-4"
+windows.tipCVSTag = "windows-21-4"
windows.changesFile = "CHANGES.msw"
windows.versionRequiredFields = (
"shebang", "emacs_is_beta", "emacs_major_version",
"emacs_minor_version",