##// 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 def __contains__(self, key):
632 def __contains__(self, key):
633 return self._repo.dirstate[key] not in "?r"
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 @propertycache
671 @propertycache
636 def _manifest(self):
672 def _manifest(self):
637 """generate a manifest corresponding to the working directory"""
673 """generate a manifest corresponding to the working directory"""
@@ -640,7 +676,6 b' class workingctx(changectx):'
640 self.status(unknown=True)
676 self.status(unknown=True)
641
677
642 man = self._parents[0].manifest().copy()
678 man = self._parents[0].manifest().copy()
643 copied = self._repo.dirstate.copies()
644 if len(self._parents) > 1:
679 if len(self._parents) > 1:
645 man2 = self.p2().manifest()
680 man2 = self.p2().manifest()
646 def getman(f):
681 def getman(f):
@@ -649,10 +684,9 b' class workingctx(changectx):'
649 return man2
684 return man2
650 else:
685 else:
651 getman = lambda f: man
686 getman = lambda f: man
652 def cf(f):
687
653 f = copied.get(f, f)
688 copied = self._repo.dirstate.copies()
654 return getman(f).flags(f)
689 ff = self._flagfunc
655 ff = self._repo.dirstate.flagfunc(cf)
656 modified, added, removed, deleted = self._status
690 modified, added, removed, deleted = self._status
657 unknown = self._unknown
691 unknown = self._unknown
658 for i, l in (("a", added), ("m", modified), ("u", unknown)):
692 for i, l in (("a", added), ("m", modified), ("u", unknown)):
@@ -767,23 +801,10 b' class workingctx(changectx):'
767 except KeyError:
801 except KeyError:
768 return ''
802 return ''
769
803
770 orig = self._repo.dirstate.copies().get(path, path)
804 try:
771
805 return self._flagfunc(path)
772 def findflag(ctx):
806 except OSError:
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':
785 return ''
807 return ''
786 return flag
787
808
788 def filectx(self, path, filelog=None):
809 def filectx(self, path, filelog=None):
789 """get a file context from the working directory"""
810 """get a file context from the working directory"""
@@ -131,17 +131,19 b' class dirstate(object):'
131 # it's safe because f is always a relative path
131 # it's safe because f is always a relative path
132 return self._rootdir + f
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 if self._checklink:
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 def f(x):
147 def f(x):
146 if os.path.islink(self._join(x)):
148 if os.path.islink(self._join(x)):
147 return 'l'
149 return 'l'
@@ -157,7 +159,8 b' class dirstate(object):'
157 return 'x'
159 return 'x'
158 return ''
160 return ''
159 return f
161 return f
160 return fallback
162 else:
163 return fallback
161
164
162 def getcwd(self):
165 def getcwd(self):
163 cwd = os.getcwd()
166 cwd = os.getcwd()
General Comments 0
You need to be logged in to leave comments. Login now