--- a/contrib/win32/win32-build.txt Tue May 01 13:23:32 2007 -0700
+++ b/contrib/win32/win32-build.txt Thu May 03 17:27:21 2007 -0500
@@ -4,7 +4,7 @@
It has the following prerequisites, at least as I build it:
Python for Windows
- http://www.python.org/ftp/python/2.4.1/python-2.4.1.msi
+ http://www.python.org/ftp/python/2.4.3/python-2.4.3.msi
MinGW
http://www.mingw.org/
@@ -21,7 +21,7 @@
Inno Setup
http://www.jrsoftware.org/isinfo.php
- ISTool
+ ISTool - optional
http://www.istool.org/default.aspx/
add_path (you need only add_path.exe in the zip file)
@@ -35,13 +35,37 @@
In a shell, build a standalone copy of the hg.exe program:
- python setup.py build -c mingw32 py2exe -b 1
+ python setup.py build -c mingw32
+ python setup.py py2exe -b 1
+
+Note: the previously suggested combined command of "python setup.py build -c
+mingw32 py2exe -b 1" doesn't work correctly anymore as it doesn't include the
+extensions in the mercurial subdirectory.
-Copy mfc71.dll and add_path.exe into the dist directory that just
-got created.
+If you want to create a file named setup.cfg with the contents:
+
+[build]
+compiler=mingw32
+
+you can skip the first build step.
+
+Copy mfc71.dll and add_path.exe into the dist directory that just got created.
-Run ISTool, and open the C:\hg\hg-release\contrib\win32\mercurial.iss
-file.
+If you use ISTool, you open the C:\hg\hg-release\contrib\win32\mercurial.iss
+file and type Ctrl-F9 to compile the installer file.
+
+Otherwise you run the Inno Setup compiler. Assuming it's on the path you run:
+
+ iscc contrib\win32\mercurial.iss
+
+The actual installer will be in the C:\hg\hg-release\Output directory.
-In ISTool, type Ctrl-F9 to compile the installer file. The actual
-installer will be in the C:\hg\hg-release\Output directory.
+To automate the steps above you may want to create a batchfile based on the
+following:
+
+ echo [build] > setup.cfg
+ echo compiler=mingw32 >> setup.cfg
+ python setup.py py2exe -b 1
+ iscc contrib\win32\mercurial.iss
+
+and run it from the root of the hg repository (c:\hg\hg-release).
--- a/mercurial/merge.py Tue May 01 13:23:32 2007 -0700
+++ b/mercurial/merge.py Thu May 03 17:27:21 2007 -0500
@@ -102,6 +102,27 @@
Find moves and copies between m1 and m2 back to limit linkrev
"""
+ def nonoverlap(d1, d2, d3):
+ "Return list of elements in d1 not in d2 or d3"
+ l = [d for d in d1 if d not in d3 and d not in d2]
+ l.sort()
+ return l
+
+ def dirname(f):
+ s = f.rfind("/")
+ if s == -1:
+ return ""
+ return f[:s]
+
+ def dirs(files):
+ d = {}
+ for f in files:
+ f = dirname(f)
+ while f not in d:
+ d[f] = True
+ f = dirname(f)
+ return d
+
def findold(fctx):
"find files that path was copied from, back to linkrev limit"
old = {}
@@ -124,33 +145,25 @@
old.sort()
return old
- def nonoverlap(d1, d2, d3):
- "Return list of elements in d1 not in d2 or d3"
- l = [d for d in d1 if d not in d3 and d not in d2]
- l.sort()
- return l
+ copy = {}
+ fullcopy = {}
def checkcopies(c, man):
'''check possible copies for filectx c'''
for of in findold(c):
- if of not in man:
+ if of not in man: # original file not in other manifest?
continue
c2 = ctx(of, man[of])
ca = c.ancestor(c2)
- if not ca: # unrelated
+ if not ca: # unrelated?
continue
+ # named changed on only one side?
if ca.path() == c.path() or ca.path() == c2.path():
- fullcopy[c.path()] = of
- if c == ca and c2 == ca: # no merge needed, ignore copy
+ fullcopy[c.path()] = of # remember for dir rename detection
+ if c == c2: # no merge needed, ignore copy
continue
copy[c.path()] = of
- def dirs(files):
- d = {}
- for f in files:
- d[os.path.dirname(f)] = True
- return d
-
if not repo.ui.configbool("merge", "followcopies", True):
return {}
@@ -159,8 +172,6 @@
return {}
dcopies = repo.dirstate.copies()
- copy = {}
- fullcopy = {}
u1 = nonoverlap(m1, m2, ma)
u2 = nonoverlap(m2, m1, ma)
ctx = util.cachefunc(lambda f, n: repo.filectx(f, fileid=n[:20]))
@@ -179,28 +190,41 @@
invalid = {}
dirmove = {}
+ # examine each file copy for a potential directory move, which is
+ # when all the files in a directory are moved to a new directory
for dst, src in fullcopy.items():
- dsrc, ddst = os.path.dirname(src), os.path.dirname(dst)
+ dsrc, ddst = dirname(src), dirname(dst)
if dsrc in invalid:
+ # already seen to be uninteresting
continue
- elif (dsrc in d1 and ddst in d1) or (dsrc in d2 and ddst in d2):
+ elif dsrc in d1 and ddst in d1:
+ # directory wasn't entirely moved locally
+ invalid[dsrc] = True
+ elif dsrc in d2 and ddst in d2:
+ # directory wasn't entirely moved remotely
invalid[dsrc] = True
elif dsrc in dirmove and dirmove[dsrc] != ddst:
+ # files from the same directory moved to two different places
invalid[dsrc] = True
- del dirmove[dsrc]
else:
+ # looks good so far
dirmove[dsrc + "/"] = ddst + "/"
+ for i in invalid:
+ if i in dirmove:
+ del dirmove[i]
+
del d1, d2, invalid
if not dirmove:
return copy
- # check unaccounted nonoverlapping files
+ # check unaccounted nonoverlapping files against directory moves
for f in u1 + u2:
if f not in fullcopy:
for d in dirmove:
if f.startswith(d):
+ # new file added in a directory that was moved, move it
copy[f] = dirmove[d] + f[len(d):]
break