Commits

Martin Vejnár  committed 6967d5f

The .hgdeps file is now loaded from repo heads.

The tip is read the last. The local .hgdeps file is only read
if it was modified.

When reading a file, existing sections are entirely replaced
by new sections, with the exception of the 'aliases' section.
New aliases replace existing aliases.

Note, that 'hg deprmalias' doesn't currently work as expected,
since the removed alias can possibly be imported from
another source.

  • Participants
  • Parent commits 40e1283

Comments (0)

Files changed (1)

 from string import Template
 
 import mercurial.node
+import mercurial.revlog
 from mercurial.i18n import _
 from mercurial import cmdutil, commands, fancyopts, hg, util, localrepo
 
 
         if opts['remove']:
             config.remove(tag, dep)
-            config.save()
+            _save_config(ui, repo, config)
         elif not dep:
             config.print_list(tag)
         else:
             config.add(tag, dep)
-            config.save()
+            _save_config(ui, repo, config)
 
 
 def depupdate(ui, repo, rev=None):
     try:
         config = _get_config(ui, repo)
         config.aliases.add_versioned(alias, type, location, args=[])
-        config.save()
+        _save_config(ui, repo, config)
     finally:
         wlock.release()
 
                     ui.status(_('skipping non-versioned alias: %s\n') % alias)
             else:
                 ui.status(_('skipping undefined alias: %s\n') % alias)
-        config.save()
+        _save_config(ui, repo, config)
     finally:
         wlock.release()
 
 # Internal classes
 
 def _get_config(ui, repo):
-    return deps_config(ui, os.path.join(repo.root, '.hgdeps'))
+    config = deps_config(ui)
+    
+    # Retrieve the set of head nodes containing
+    # .hgdeps file. The tip node should be processed
+    # last. The snippet is copied from
+    # mercurial.localrepo.locarepository._hgtagsnodes
+    heads = repo.heads()
+    heads.reverse()
+    last = {}
+    filenodes = []
+    for node in heads:
+        c = repo[node]
+        try:
+            fnode = c.filenode('.hgdeps')
+        except mercurial.revlog.LookupError:
+            continue
+        filenodes.append((node, fnode))
+        if fnode in last:
+            filenodes[last[fnode]] = None
+        last[fnode] = len(filenodes) - 1
+    
+    import StringIO
+    f = None
+    for node, fnode in filenodes:
+        f = (f and f.filectx(fnode) or
+             repo.filectx('.hgdeps', fileid=fnode))
+        config.load(StringIO.StringIO(f.data()))
+    
+    status = repo.status()
+    if '.hgdeps' not in status[0] and '.hgdeps' not in status[1]:
+        return config
+    
+    filename = os.path.join(repo.root, '.hgdeps')
+    try:
+        f = open(filename, 'rb')
+    except IOError:
+        return config
+    
+    try:
+        config.load(f)
+    finally:
+        f.close()
+    
+    return config
+
+def _save_config(ui, repo, config):
+    text = config.get_text()
+    
+    f = open(os.path.join(repo.root, '.hgdeps'), 'wb')
+    try:
+        f.write(text)
+    finally:
+        f.close()
+    
+    if repo.dirstate['.hgdeps'] == '?':
+        repo.add(['.hgdeps'])
 
 def _find_deplist(ui, repo, config, rev):
     if rev is not None and config.has_tag(rev):
             self.add_new(name, scmtype, location, args)
 
 class deps_config:
-    def __init__(self, ui, config_file):
+    def __init__(self, ui):
         self._ui = ui
         self._order = []
         self._tags = {}
-        self._config_file = config_file
-
         self.aliases = deps_aliases(ui)
-        try:
-            self._read_config()
-        except IOError:
-            True
 
     def tag(self, tag):
         self._check_tag(tag)
 
     def print_all(self):
         '''prints the list of the registered dependency lists'''
-        self._ui.status(self._get_text())
+        self._ui.status(self.get_text())
     
-    def save(self):
-        text = self._get_text()
-        
-        f = open(self._config_file, 'wb')
-        try:
-            f.write(text)
-        finally:
-            f.close()
-    
-    def _get_text(self):
+    def get_text(self):
         res = []
         versioned_aliases = [alias for alias in self.aliases if self.aliases[alias].is_versioned()]
         if versioned_aliases:
         return ''.join(res)
 
     def _add_tag(self, tag):
-        self._order.append(tag)
+        if tag not in self._tags:
+            self._order.append(tag)
         self._tags[tag] = []
 
     def _remove_tag(self, tag):
         if not self.has_tag(tag):
             raise util.Abort(_("dependency list '%s' is not registered" % tag))
 
-    def _read_config(self):
+    def load(self, f):
         p_tag = re.compile(r'\[(\S+)\]')
         p_dep = re.compile(r'(\S+)\s+(\S+)\s+(\S+)')
-        f = open(self._config_file, 'rb')
         tag = None
         for i, line in enumerate(f.readlines()):
             m = p_tag.search(line)
                         raise util.Abort(_("in .hgdeps, depedency %s already"
                                            " registered for '%s'" % (dep, tag)))
                     self._tags[tag].append(dep)
-        f.close()
 
 _cloneopts = [
     ('', 'pull', None, _('use pull protocol to copy metadata')),