Commits

Peter Bex committed 482156f

Add update-meta command that updates the meta file

  • Participants
  • Parent commits dde5508

Comments (0)

Files changed (1)

 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.
     '''
     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)
     
     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', '',
                 ('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")
 }