##// END OF EJS Templates
windows: recompute flags when committing a merge (issue1802)...
Matt Mackall -
r15337:cf5f9df6 stable
parent child Browse files
Show More
@@ -0,0 +1,69 b''
1 Create extension that can disable exec checks:
2
3 $ cat > noexec.py <<EOF
4 > from mercurial import extensions, util
5 > def setflags(orig, f, l, x):
6 > pass
7 > def checkexec(orig, path):
8 > return False
9 > def extsetup(ui):
10 > extensions.wrapfunction(util, 'setflags', setflags)
11 > extensions.wrapfunction(util, 'checkexec', checkexec)
12 > EOF
13
14 $ hg init unix-repo
15 $ cd unix-repo
16 $ touch a
17 $ hg add a
18 $ hg commit -m 'unix: add a'
19 $ hg clone . ../win-repo
20 updating to branch default
21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 $ chmod +x a
23 $ hg commit -m 'unix: chmod a'
24 $ hg manifest -v
25 755 * a
26
27 $ cd ../win-repo
28
29 $ touch b
30 $ hg add b
31 $ hg commit -m 'win: add b'
32
33 $ hg manifest -v
34 644 a
35 644 b
36
37 $ hg pull
38 pulling from $TESTTMP/unix-repo
39 searching for changes
40 adding changesets
41 adding manifests
42 adding file changes
43 added 1 changesets with 0 changes to 0 files (+1 heads)
44 (run 'hg heads' to see heads, 'hg merge' to merge)
45
46 $ hg manifest -v -r tip
47 755 * a
48
49 Simulate a Windows merge:
50
51 $ hg --config extensions.n=$TESTTMP/noexec.py merge --debug
52 searching for copies back to rev 1
53 unmatched files in local:
54 b
55 resolving manifests
56 overwrite None partial False
57 ancestor a03b0deabf2b local d6fa54f68ae1+ remote 2d8bcf2dda39
58 a: update permissions -> e
59 updating: a 1/1 files (100.00%)
60 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 (branch merge, don't forget to commit)
62
63 Simulate a Windows commit:
64
65 $ hg --config extensions.n=$TESTTMP/noexec.py commit -m 'win: merge'
66
67 $ hg manifest -v
68 755 * a
69 644 b
@@ -632,6 +632,42 b' class workingctx(changectx):'
632 632 def __contains__(self, key):
633 633 return self._repo.dirstate[key] not in "?r"
634 634
635 def _buildflagfunc(self):
636 # Create a fallback function for getting file flags when the
637 # filesystem doesn't support them
638
639 copiesget = self._repo.dirstate.copies().get
640
641 if len(self._parents) < 2:
642 # when we have one parent, it's easy: copy from parent
643 man = self._parents[0].manifest()
644 def func(f):
645 f = copiesget(f, f)
646 return man.flags(f)
647 else:
648 # merges are tricky: we try to reconstruct the unstored
649 # result from the merge (issue1802)
650 p1, p2 = self._parents
651 pa = p1.ancestor(p2)
652 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
653
654 def func(f):
655 f = copiesget(f, f) # may be wrong for merges with copies
656 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
657 if fl1 == fl2:
658 return fl1
659 if fl1 == fla:
660 return fl2
661 if fl2 == fla:
662 return fl1
663 return '' # punt for conflicts
664
665 return func
666
667 @propertycache
668 def _flagfunc(self):
669 return self._repo.dirstate.flagfunc(self._buildflagfunc)
670
635 671 @propertycache
636 672 def _manifest(self):
637 673 """generate a manifest corresponding to the working directory"""
@@ -640,7 +676,6 b' class workingctx(changectx):'
640 676 self.status(unknown=True)
641 677
642 678 man = self._parents[0].manifest().copy()
643 copied = self._repo.dirstate.copies()
644 679 if len(self._parents) > 1:
645 680 man2 = self.p2().manifest()
646 681 def getman(f):
@@ -649,10 +684,9 b' class workingctx(changectx):'
649 684 return man2
650 685 else:
651 686 getman = lambda f: man
652 def cf(f):
653 f = copied.get(f, f)
654 return getman(f).flags(f)
655 ff = self._repo.dirstate.flagfunc(cf)
687
688 copied = self._repo.dirstate.copies()
689 ff = self._flagfunc
656 690 modified, added, removed, deleted = self._status
657 691 unknown = self._unknown
658 692 for i, l in (("a", added), ("m", modified), ("u", unknown)):
@@ -767,23 +801,10 b' class workingctx(changectx):'
767 801 except KeyError:
768 802 return ''
769 803
770 orig = self._repo.dirstate.copies().get(path, path)
771
772 def findflag(ctx):
773 mnode = ctx.changeset()[0]
774 node, flag = self._repo.manifest.find(mnode, orig)
775 ff = self._repo.dirstate.flagfunc(lambda x: flag or '')
776 try:
777 return ff(path)
778 except OSError:
779 pass
780
781 flag = findflag(self._parents[0])
782 if flag is None and len(self.parents()) > 1:
783 flag = findflag(self._parents[1])
784 if flag is None or self._repo.dirstate[path] == 'r':
804 try:
805 return self._flagfunc(path)
806 except OSError:
785 807 return ''
786 return flag
787 808
788 809 def filectx(self, path, filelog=None):
789 810 """get a file context from the working directory"""
@@ -131,17 +131,19 b' class dirstate(object):'
131 131 # it's safe because f is always a relative path
132 132 return self._rootdir + f
133 133
134 def flagfunc(self, fallback):
134 def flagfunc(self, buildfallback):
135 if self._checklink and self._checkexec:
136 def f(x):
137 p = self._join(x)
138 if os.path.islink(p):
139 return 'l'
140 if util.isexec(p):
141 return 'x'
142 return ''
143 return f
144
145 fallback = buildfallback()
135 146 if self._checklink:
136 if self._checkexec:
137 def f(x):
138 p = self._join(x)
139 if os.path.islink(p):
140 return 'l'
141 if util.isexec(p):
142 return 'x'
143 return ''
144 return f
145 147 def f(x):
146 148 if os.path.islink(self._join(x)):
147 149 return 'l'
@@ -157,7 +159,8 b' class dirstate(object):'
157 159 return 'x'
158 160 return ''
159 161 return f
160 return fallback
162 else:
163 return fallback
161 164
162 165 def getcwd(self):
163 166 cwd = os.getcwd()
General Comments 0
You need to be logged in to leave comments. Login now