mercurial/hg.py
changeset 536 c15b4bc0a11c
parent 529 aace5b681fe9
child 537 411e05b04ffa
equal deleted inserted replaced
535:fba26990604a 536:c15b4bc0a11c
   286                 f = f + "\0" + c
   286                 f = f + "\0" + c
   287             e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
   287             e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
   288             st.write(e + f)
   288             st.write(e + f)
   289         self.dirty = 0
   289         self.dirty = 0
   290 
   290 
   291     def dup(self):
   291     def changes(self, files, ignore):
   292         self.read()
   292         self.read()
   293         return self.map.copy()
   293         dc = self.map.copy()
       
   294         lookup, changed, added, unknown = [], [], [], []
       
   295 
       
   296         # compare all files by default
       
   297         if not files: files = [self.root]
       
   298 
       
   299         def uniq(g):
       
   300             seen = {}
       
   301             for f in g:
       
   302                 if f not in seen:
       
   303                     seen[f] = 1
       
   304                     yield f
       
   305 
       
   306         # recursive generator of all files listed
       
   307         def walk(files):
       
   308             for f in uniq(files):
       
   309                 if os.path.isdir(f):
       
   310                     for dir, subdirs, fl in os.walk(f):
       
   311                         d = dir[len(self.root) + 1:]
       
   312                         if ".hg" in subdirs: subdirs.remove(".hg")
       
   313                         for fn in fl:
       
   314                             fn = util.pconvert(os.path.join(d, fn))
       
   315                             yield fn
       
   316                 else:
       
   317                     yield f[len(self.root) + 1:]
       
   318 
       
   319         for fn in uniq(walk(files)):
       
   320             try: s = os.stat(os.path.join(self.root, fn))
       
   321             except: continue
       
   322 
       
   323             if fn in dc:
       
   324                 c = dc[fn]
       
   325                 del dc[fn]
       
   326 
       
   327                 if c[0] == 'm':
       
   328                     changed.append(fn)
       
   329                 elif c[0] == 'a':
       
   330                     added.append(fn)
       
   331                 elif c[0] == 'r':
       
   332                     unknown.append(fn)
       
   333                 elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100:
       
   334                     changed.append(fn)
       
   335                 elif c[1] != s.st_mode or c[3] != s.st_mtime:
       
   336                     lookup.append(fn)
       
   337             else:
       
   338                 if not ignore(fn): unknown.append(fn)
       
   339 
       
   340         return (lookup, changed, added, dc.keys(), unknown)
   294 
   341 
   295 # used to avoid circular references so destructors work
   342 # used to avoid circular references so destructors work
   296 def opener(base):
   343 def opener(base):
   297     p = base
   344     p = base
   298     def o(path, mode="r"):
   345     def o(path, mode="r"):
   566                 elif s == 'r':
   613                 elif s == 'r':
   567                     remove.append(f)
   614                     remove.append(f)
   568                 else:
   615                 else:
   569                     self.ui.warn("%s not tracked!\n" % f)
   616                     self.ui.warn("%s not tracked!\n" % f)
   570         else:
   617         else:
   571             (c, a, d, u) = self.diffdir(self.root)
   618             (c, a, d, u) = self.changes(None, None)
   572             commit = c + a
   619             commit = c + a
   573             remove = d
   620             remove = d
   574 
   621 
   575         if not commit and not remove:
   622         if not commit and not remove:
   576             self.ui.status("nothing changed\n")
   623             self.ui.status("nothing changed\n")
   642 
   689 
   643         self.dirstate.setparents(n)
   690         self.dirstate.setparents(n)
   644         self.dirstate.update(new, "n")
   691         self.dirstate.update(new, "n")
   645         self.dirstate.forget(remove)
   692         self.dirstate.forget(remove)
   646 
   693 
   647     def diffdir(self, path, changeset = None):
   694     def changes(self, node1, node2, *files):
   648         changed = []
   695         # changed, added, deleted, unknown
   649         added = []
   696         c, a, d, u, mf1 = [], [], [], [], None
   650         unknown = []
   697 
   651         mf = {}
   698         def fcmp(fn, mf):
   652 
       
   653         if changeset:
       
   654             change = self.changelog.read(changeset)
       
   655             mf = self.manifest.read(change[0])
       
   656             dc = dict.fromkeys(mf)
       
   657         else:
       
   658             changeset = self.dirstate.parents()[0]
       
   659             change = self.changelog.read(changeset)
       
   660             mf = self.manifest.read(change[0])
       
   661             dc = self.dirstate.dup()
       
   662 
       
   663         def fcmp(fn):
       
   664             t1 = self.wfile(fn).read()
   699             t1 = self.wfile(fn).read()
   665             t2 = self.file(fn).revision(mf[fn])
   700             t2 = self.file(fn).revision(mf[fn])
   666             return cmp(t1, t2)
   701             return cmp(t1, t2)
   667 
   702 
   668         for dir, subdirs, files in os.walk(path):
   703         # are we comparing the working directory?
   669             d = dir[len(self.root)+1:]
   704         if not node1:
   670             if ".hg" in subdirs: subdirs.remove(".hg")
   705             l, c, a, d, u = self.dirstate.changes(files, self.ignore)
   671 
   706 
   672             for f in files:
   707             # are we comparing working dir against its parent?
   673                 fn = util.pconvert(os.path.join(d, f))
   708             if not node2:
   674                 try: s = os.stat(os.path.join(self.root, fn))
   709                 if l:
   675                 except: continue
   710                     # do a full compare of any files that might have changed
   676                 if fn in dc:
   711                     change = self.changelog.read(self.dirstate.parents()[0])
   677                     c = dc[fn]
   712                     mf1 = self.manifest.read(change[0])
   678                     del dc[fn]
   713                     for f in lookup:
   679                     if not c:
   714                         if fcmp(f, mf):
   680                         if fcmp(fn):
   715                             c.append(f)
   681                             changed.append(fn)
   716                 return (c, a, d, u)
   682                     elif c[0] == 'm':
   717 
   683                         changed.append(fn)
   718         # are we comparing working dir against non-tip?
   684                     elif c[0] == 'a':
   719         # generate a pseudo-manifest for the working dir
   685                         added.append(fn)
   720         if not node1:
   686                     elif c[0] == 'r':
   721             if not mf1:
   687                         unknown.append(fn)
   722                 change = self.changelog.read(self.dirstate.parents()[0])
   688                     elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100:
   723                 mf1 = self.manifest.read(change[0])
   689                         changed.append(fn)
   724             for f in a + c + l:
   690                     elif c[1] != s.st_mode or c[3] != s.st_mtime:
   725                 mf1[f] = ""
   691                         if fcmp(fn):
   726             for f in d:
   692                             changed.append(fn)
   727                 if f in mf1: del mf1[f]
   693                 else:
   728         else:
   694                     if self.ignore(fn): continue
   729             change = self.changelog.read(node1)
   695                     unknown.append(fn)
   730             mf1 = self.manifest.read(change[0])
   696 
   731 
   697         deleted = dc.keys()
       
   698         deleted.sort()
       
   699 
       
   700         return (changed, added, deleted, unknown)
       
   701 
       
   702     def diffrevs(self, node1, node2):
       
   703         changed, added = [], []
       
   704 
       
   705         change = self.changelog.read(node1)
       
   706         mf1 = self.manifest.read(change[0])
       
   707         change = self.changelog.read(node2)
   732         change = self.changelog.read(node2)
   708         mf2 = self.manifest.read(change[0])
   733         mf2 = self.manifest.read(change[0])
   709 
   734 
   710         for fn in mf2:
   735         for fn in mf2:
   711             if mf1.has_key(fn):
   736             if mf1.has_key(fn):
   712                 if mf1[fn] != mf2[fn]:
   737                 if mf1[fn] != mf2[fn]:
   713                     changed.append(fn)
   738                     if mf1[fn] != "" or fcmp(fn, mf2):
       
   739                         c.append(fn)
   714                 del mf1[fn]
   740                 del mf1[fn]
   715             else:
   741             else:
   716                 added.append(fn)
   742                 a.append(fn)
   717 
   743 
   718         deleted = mf1.keys()
   744         d = mf1.keys()
   719         deleted.sort()
   745         d.sort()
   720 
   746 
   721         return (changed, added, deleted)
   747         return (c, a, d, u)
   722 
   748 
   723     def add(self, list):
   749     def add(self, list):
   724         for f in list:
   750         for f in list:
   725             p = self.wjoin(f)
   751             p = self.wjoin(f)
   726             if not os.path.isfile(p):
   752             if not os.path.isfile(p):
  1042         m2 = self.manifest.read(m2n)
  1068         m2 = self.manifest.read(m2n)
  1043         mf2 = self.manifest.readflags(m2n)
  1069         mf2 = self.manifest.readflags(m2n)
  1044         ma = self.manifest.read(man)
  1070         ma = self.manifest.read(man)
  1045         mfa = self.manifest.readflags(man)
  1071         mfa = self.manifest.readflags(man)
  1046 
  1072 
  1047         (c, a, d, u) = self.diffdir(self.root)
  1073         (c, a, d, u) = self.changes(None, None)
  1048 
  1074 
  1049         # is this a jump, or a merge?  i.e. is there a linear path
  1075         # is this a jump, or a merge?  i.e. is there a linear path
  1050         # from p1 to p2?
  1076         # from p1 to p2?
  1051         linear_path = (pa == p1 or pa == p2)
  1077         linear_path = (pa == p1 or pa == p2)
  1052 
  1078