aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Bex <peter@more-magic.net>2011-04-03 22:21:09 +0200
committerPeter Bex <peter@more-magic.net>2011-04-03 22:21:09 +0200
commit1ce44e728f276bfd12b8e1bb13e960c730eef9a5 (patch)
tree6b26bc005af3cfc4feef543b100bd9e0348fcb0e
parentb60128ec8b1ea85cbb18b6df8440a4f278b10331 (diff)
downloadhg-egg-author-1ce44e728f276bfd12b8e1bb13e960c730eef9a5.tar.gz
Add update-meta command that updates the meta file
-rw-r--r--egg-author.py125
1 files changed, 107 insertions, 18 deletions
diff --git a/egg-author.py b/egg-author.py
index c897f04..ddeeb54 100644
--- a/egg-author.py
+++ b/egg-author.py
@@ -24,37 +24,42 @@ from mercurial import cmdutil, commands, util
import mercurial.match as matchmod
# This is probably really really dumb code. I don't know python
-def _find_release_info_file(repo):
+def _find_egg_info_file(repo, type):
stat = repo.status(clean=True)
for x in stat[:5]:
for fn in x:
- if fnmatch.fnmatch(fn, '*.release-info'):
+ if fnmatch.fnmatch(fn, '*.%s' % type):
raise util.Abort(_('%s is modified (please commit or revert '
'and retry)') % fn)
- release_info_file = None
+ egg_info_file = None
- for x in stat[5:]:
+ for x in stat[6:]:
for fn in x:
- if fnmatch.fnmatch(fn, "*.release-info"):
- if release_info_file:
- raise util.Abort(_('Found more than one release-info file!'))
+ if fnmatch.fnmatch(fn, "*.%s" % type):
+ if egg_info_file:
+ raise util.Abort(_('Found more than one %s file!' % type))
else:
- release_info_file = fn
+ egg_info_file = fn
- if not release_info_file:
- raise util.Abort(_('Could not find release-info file. You need to '
- 'create one first. See %s for more info.')
- % 'http://wiki.call-cc.org/releasing-your-egg')
+ if not egg_info_file:
+ if type == 'release-info':
+ help_uri = 'http://wiki.call-cc.org/releasing-your-egg'
+ elif type == 'meta':
+ help_uri = 'http://wiki.call-cc.org/Metafile%20reference'
+ else:
+ raise util.Abort(_('No help URI for egg file type %s') % type)
+ raise util.Abort(_('Could not find %s file. You need to '
+ 'create one first. See %s for more info.') % help_uri)
- return release_info_file
+ return egg_info_file
-def _clean_scheme_string(s):
+def _to_scheme_string(s):
# This is a pathetic attempt at being safe. You shouldn't be using
# these names anywway, and the user should be already be trusted when
# they're allowed to commit.
- return re.sub(r'\\', r'\\\\', re.sub(r'"', r'\\"', s))
+ return '"' + re.sub(r'\\', r'\\\\', re.sub(r'"', r'\\"', s)) + '"'
def eggtag(ui, repo, name1, *names, **opts):
'''Tag a Chicken egg for release.
@@ -65,7 +70,7 @@ def eggtag(ui, repo, name1, *names, **opts):
'''
allnames = [t.strip() for t in (name1,) + names]
- release_info_file = _find_release_info_file(repo)
+ release_info_file = _find_egg_info_file(repo, 'release-info')
fp = repo.wfile(release_info_file, 'r+')
commands.tag(ui, repo, name1, *names, **opts)
@@ -73,12 +78,93 @@ def eggtag(ui, repo, name1, *names, **opts):
relinfo_message = ('Updated release-info file for release tag %s' % (', '.join(allnames)))
fp.seek(0, 2) # to the end
for n in allnames:
- fp.write("(release \"%s\")\n" % _clean_scheme_string(n))
+ fp.write("(release %s)\n" % _to_scheme_string(n))
fp.close()
m = matchmod.exact(repo.root, '', [release_info_file])
repo.commit(text=relinfo_message, user=opts.get('user'), date=opts.get('date'), match=m)
+def read_byte(f,res):
+ byte = f.read(1)
+ if (len(byte) == 0):
+ return None
+ else:
+ res.extend(byte[0])
+ return byte[0]
+
+class FoundFiles(Exception):
+ def __init__(self, val):
+ self.res = val
+
+# A *really* hacky s-expression reader
+def _read_over_files(f, res, end = None):
+ byte = read_byte(f,res)
+
+ first_identifier = True
+
+ while byte != None and byte != end:
+ if byte == '"':
+ byte = read_byte(f,res)
+ while byte != None and byte != '"':
+ if byte == '\\': # Escaped, so just read it without interpretation
+ read_byte(f,res)
+ byte = read_byte(f,res)
+ byte = read_byte(f,res)
+ elif byte.isspace():
+ byte = read_byte(f,res)
+ elif byte == ';':
+ byte = read_byte(f,res)
+ while byte != None and byte != '\n':
+ byte = read_byte(f,res)
+ elif byte == '(':
+ _read_over_files(f, res, ')')
+ byte = read_byte(f,res)
+ else: # Assume identifier
+ identifier = []
+ while byte != None and not byte.isspace() and byte != '(' and byte != ')' and byte != ';' and byte != '"':
+ identifier.extend(byte)
+ byte = read_byte(f,res)
+ if first_identifier and ''.join(identifier) == 'files':
+ # Skip until end of list
+ _read_over_files(f, [], ')')
+ raise FoundFiles(res)
+
+ first_identifier = False
+ return res
+
+def update_meta(ui, repo):
+ '''Update the FILES entry in an egg's meta-file.
+
+ Only version-controlled files are added.'''
+
+ meta_file = _find_egg_info_file(repo, 'meta')
+ files = repo.status(clean=True)[6:][0]
+ files.remove('.hgtags')
+
+ # A list without the parens around it
+ files_list = ' '.join(map(_to_scheme_string, files))
+
+ mf = repo.wfile(meta_file, 'rb')
+ try:
+ s = ''.join(_read_over_files(mf, []))
+ s = s.rstrip() # Assuming no trailing comments...
+ s = s[:len(s)-1] + '\n (files ' + files_list + '))\n'
+ except FoundFiles, value:
+ s = ''.join(value.res) + files_list + ')'
+ s += mf.read() # the rest of the file
+ mf.close
+
+ # reopen and write out the new string
+ mf = repo.wfile(meta_file, 'w')
+ mf.write(s)
+ mf.close
+
+ # This doesn't work because repo.status operates on a cache or something
+ #if len(repo.status(match=matchmod.exact('.', '.', [meta_file]))[0]) == 0:
+ # ui.status(_('Meta-file %s was already up-to-date\n') % meta_file)
+ #else:
+ ui.status(_('Meta-file %s is updated\n') % meta_file)
+
cmdtable = {
"eggtag": (eggtag,
[('r', 'rev', '',
@@ -88,5 +174,8 @@ cmdtable = {
('m', 'message', '',
_('use <text> as commit message'), _('TEXT')),
],
- "hg eggtag [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...")
+ "hg eggtag [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME..."),
+ "update-meta": (update_meta,
+ [],
+ "hg update-meta")
}