Merge Chris's changes with mine.
authorBryan O'Sullivan <bos@serpentine.com>
Fri, 12 Aug 2005 09:58:35 -0800
changeset 874 d4cb383e7de77eb7533af33b9b01627a4eb8dea0
parent 871 c2e77581bc841e5bf978bc51e3323d1b49916a9e (current diff)
parent 873 4480e035d838cc79564f3ebe3938b024d2c7cbc5 (diff)
child 878 781266a78fe166a3513ed36656878fd2a04143d0
push id1
push usergszorc@mozilla.com
push dateWed, 18 Mar 2015 16:34:57 +0000
Merge Chris's changes with mine.
.hgignore
CONTRIBUTORS
TODO
doc/hg.1.txt
mercurial/commands.py
mercurial/hg.py
mercurial/hgweb.py
mercurial/revlog.py
mercurial/util.py
templates/map
tests/test-help
tests/test-help.out
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -388,21 +388,20 @@ def add(ui, repo, *pats, **opts):
             names.append(abs)
     repo.add(names)
 
 def addremove(ui, repo, *pats, **opts):
     """add all new files, delete all missing files"""
     q = dict(zip(pats, pats))
     add, remove = [], []
     for src, abs, rel in walk(repo, pats, opts):
-        if src == 'f':
-            if repo.dirstate.state(abs) == '?':
-                add.append(abs)
-                if rel not in q: ui.status('adding ', rel, '\n')
-        elif repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
+        if src == 'f' and repo.dirstate.state(abs) == '?':
+            add.append(abs)
+            if rel not in q: ui.status('adding ', rel, '\n')
+        if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
             remove.append(abs)
             if rel not in q: ui.status('removing ', rel, '\n')
     repo.add(add)
     repo.remove(remove)
 
 def annotate(ui, repo, *pats, **opts):
     """show changeset information per file line"""
     def getnode(rev):
@@ -627,19 +626,21 @@ def diff(ui, repo, *pats, **opts):
     revs = []
     if opts['rev']:
         revs = map(lambda x: repo.lookup(x), opts['rev'])
 
     if len(revs) > 2:
         raise util.Abort("too many revisions to diff")
 
     files = []
-    roots, match, results = makewalk(repo, pats, opts)
-    for src, abs, rel in results:
-        files.append(abs)
+    match = util.always
+    if pats:
+        roots, match, results = makewalk(repo, pats, opts)
+        for src, abs, rel in results:
+            files.append(abs)
     dodiff(sys.stdout, ui, repo, files, *revs, **{'match': match})
 
 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
     node = repo.lookup(changeset)
     prev, other = repo.changelog.parents(node)
     change = repo.changelog.read(node)
 
     fp = make_file(repo, repo.changelog, opts['output'],
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -435,21 +435,60 @@ class dirstate:
         for f, e in self.map.items():
             c = self.copied(f)
             if c:
                 f = f + "\0" + c
             e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
             st.write(e + f)
         self.dirty = 0
 
-    def walk(self, files = None, match = util.always):
+    def filterfiles(self, files):
+        ret = {}
+        unknown = []
+
+        for x in files:
+            if x is '.':
+                return self.map.copy()
+            if x not in self.map:
+                unknown.append(x)
+            else:
+                ret[x] = self.map[x]
+                
+        if not unknown:
+            return ret
+
+        b = self.map.keys()
+        b.sort()
+        blen = len(b)
+
+        for x in unknown:
+            bs = bisect.bisect(b, x)
+            if bs != 0 and  b[bs-1] == x: 
+                ret[x] = self.map[x]
+                continue
+            while bs < blen:
+                s = b[bs]
+                if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/':
+                    ret[s] = self.map[s]
+                else:
+                    break
+                bs += 1
+        return ret
+
+    def walk(self, files = None, match = util.always, dc=None):
         self.read()
-        dc = self.map.copy()
+
         # walk all files by default
-        if not files: files = [self.root]
+        if not files:
+            files = [self.root]
+            if not dc:
+                dc = self.map.copy()
+        elif not dc:
+            dc = self.filterfiles(files)
+                    
         known = {'.hg': 1}
         def seen(fn):
             if fn in known: return True
             known[fn] = 1
         def traverse():
             for f in util.unique(files):
                 f = os.path.join(self.root, f)
                 if os.path.isdir(f):
@@ -477,29 +516,30 @@ class dirstate:
                 yield 'm', k
 
         # yield only files that match: all in dirstate, others only if
         # not in .hgignore
 
         for src, fn in util.unique(traverse()):
             fn = os.path.normpath(fn)
             if seen(fn): continue
-            if fn in dc:
-                del dc[fn]
-            elif self.ignore(fn):
+            if fn not in dc and self.ignore(fn):
                 continue
             if match(fn):
                 yield src, fn
 
     def changes(self, files = None, match = util.always):
         self.read()
-        dc = self.map.copy()
+        if not files:
+            dc = self.map.copy()
+        else:
+            dc = self.filterfiles(files)
         lookup, changed, added, unknown = [], [], [], []
 
-        for src, fn in self.walk(files, match):
+        for src, fn in self.walk(files, match, dc=dc):
             try: s = os.stat(os.path.join(self.root, fn))
             except: continue
 
             if fn in dc:
                 c = dc[fn]
                 del dc[fn]
 
                 if c[0] == 'm':