Show More
@@ -1,140 +1,165 | |||||
1 | # repoview.py - Filtered view of a localrepo object |
|
1 | # repoview.py - Filtered view of a localrepo object | |
2 | # |
|
2 | # | |
3 | # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org> |
|
3 | # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org> | |
4 | # Logilab SA <contact@logilab.fr> |
|
4 | # Logilab SA <contact@logilab.fr> | |
5 | # |
|
5 | # | |
6 | # This software may be used and distributed according to the terms of the |
|
6 | # This software may be used and distributed according to the terms of the | |
7 | # GNU General Public License version 2 or any later version. |
|
7 | # GNU General Public License version 2 or any later version. | |
8 |
|
8 | |||
9 | import copy |
|
9 | import copy | |
10 | import phases |
|
10 | import phases | |
11 | import util |
|
11 | import util | |
12 |
|
12 | |||
13 |
|
13 | |||
14 | def computehidden(repo): |
|
14 | def computehidden(repo): | |
15 | """compute the set of hidden revision to filter |
|
15 | """compute the set of hidden revision to filter | |
16 |
|
16 | |||
17 | During most operation hidden should be filtered.""" |
|
17 | During most operation hidden should be filtered.""" | |
18 | assert not repo.changelog.filteredrevs |
|
18 | assert not repo.changelog.filteredrevs | |
19 | if repo.obsstore: |
|
19 | if repo.obsstore: | |
20 | return frozenset(repo.revs('hidden()')) |
|
20 | return frozenset(repo.revs('hidden()')) | |
21 | return frozenset() |
|
21 | return frozenset() | |
22 |
|
22 | |||
23 | def computeunserved(repo): |
|
23 | def computeunserved(repo): | |
24 | """compute the set of revision that should be filtered when used a server |
|
24 | """compute the set of revision that should be filtered when used a server | |
25 |
|
25 | |||
26 | Secret and hidden changeset should not pretend to be here.""" |
|
26 | Secret and hidden changeset should not pretend to be here.""" | |
27 | assert not repo.changelog.filteredrevs |
|
27 | assert not repo.changelog.filteredrevs | |
28 | # fast path in simple case to avoid impact of non optimised code |
|
28 | # fast path in simple case to avoid impact of non optimised code | |
29 | if phases.hassecret(repo) or repo.obsstore: |
|
29 | if phases.hassecret(repo) or repo.obsstore: | |
30 | return frozenset(repo.revs('hidden() + secret()')) |
|
30 | return frozenset(repo.revs('hidden() + secret()')) | |
31 | return frozenset() |
|
31 | return frozenset() | |
32 |
|
32 | |||
33 | def computemutable(repo): |
|
33 | def computemutable(repo): | |
34 | """compute the set of revision that should be filtered when used a server |
|
34 | """compute the set of revision that should be filtered when used a server | |
35 |
|
35 | |||
36 | Secret and hidden changeset should not pretend to be here.""" |
|
36 | Secret and hidden changeset should not pretend to be here.""" | |
37 | assert not repo.changelog.filteredrevs |
|
37 | assert not repo.changelog.filteredrevs | |
38 | # fast check to avoid revset call on huge repo |
|
38 | # fast check to avoid revset call on huge repo | |
39 | if util.any(repo._phasecache.phaseroots[1:]): |
|
39 | if util.any(repo._phasecache.phaseroots[1:]): | |
40 | return frozenset(repo.revs('draft() + secret()')) |
|
40 | return frozenset(repo.revs('draft() + secret()')) | |
41 | return frozenset() |
|
41 | return frozenset() | |
42 |
|
42 | |||
|
43 | def computeimpactable(repo): | |||
|
44 | """Everything impactable by mutable revision | |||
|
45 | ||||
|
46 | The mutable filter still have some chance to get invalidated. This will | |||
|
47 | happen when: | |||
|
48 | ||||
|
49 | - you garbage collect hidden changeset, | |||
|
50 | - public phase is moved backward, | |||
|
51 | - something is changed in the filtering (this could be fixed) | |||
|
52 | ||||
|
53 | This filter out any mutable changeset and any public changeset that may be | |||
|
54 | impacted by something happening to a mutable revision. | |||
|
55 | ||||
|
56 | This is achieved by filtered everything with a revision number egal or | |||
|
57 | higher than the first mutable changeset is filtered.""" | |||
|
58 | assert not repo.changelog.filteredrevs | |||
|
59 | cl = repo.changelog | |||
|
60 | firstmutable = len(cl) | |||
|
61 | for roots in repo._phasecache.phaseroots[1:]: | |||
|
62 | if roots: | |||
|
63 | firstmutable = min(firstmutable, min(cl.rev(r) for r in roots)) | |||
|
64 | return frozenset(xrange(firstmutable, len(cl))) | |||
|
65 | ||||
43 | # function to compute filtered set |
|
66 | # function to compute filtered set | |
44 | filtertable = {'hidden': computehidden, |
|
67 | filtertable = {'hidden': computehidden, | |
45 | 'unserved': computeunserved, |
|
68 | 'unserved': computeunserved, | |
46 |
'mutable': computemutable |
|
69 | 'mutable': computemutable, | |
|
70 | 'impactable': computeimpactable} | |||
47 | ### Nearest subset relation |
|
71 | ### Nearest subset relation | |
48 | # Nearest subset of filter X is a filter Y so that: |
|
72 | # Nearest subset of filter X is a filter Y so that: | |
49 | # * Y is included in X, |
|
73 | # * Y is included in X, | |
50 | # * X - Y is as small as possible. |
|
74 | # * X - Y is as small as possible. | |
51 | # This create and ordering used for branchmap purpose. |
|
75 | # This create and ordering used for branchmap purpose. | |
52 | # the ordering may be partial |
|
76 | # the ordering may be partial | |
53 | subsettable = {None: 'hidden', |
|
77 | subsettable = {None: 'hidden', | |
54 | 'hidden': 'unserved', |
|
78 | 'hidden': 'unserved', | |
55 |
'unserved': 'mutable' |
|
79 | 'unserved': 'mutable', | |
|
80 | 'mutable': 'impactable'} | |||
56 |
|
81 | |||
57 | def filteredrevs(repo, filtername): |
|
82 | def filteredrevs(repo, filtername): | |
58 | """returns set of filtered revision for this filter name""" |
|
83 | """returns set of filtered revision for this filter name""" | |
59 | if filtername not in repo.filteredrevcache: |
|
84 | if filtername not in repo.filteredrevcache: | |
60 | func = filtertable[filtername] |
|
85 | func = filtertable[filtername] | |
61 | repo.filteredrevcache[filtername] = func(repo.unfiltered()) |
|
86 | repo.filteredrevcache[filtername] = func(repo.unfiltered()) | |
62 | return repo.filteredrevcache[filtername] |
|
87 | return repo.filteredrevcache[filtername] | |
63 |
|
88 | |||
64 | class repoview(object): |
|
89 | class repoview(object): | |
65 | """Provide a read/write view of a repo through a filtered changelog |
|
90 | """Provide a read/write view of a repo through a filtered changelog | |
66 |
|
91 | |||
67 | This object is used to access a filtered version of a repository without |
|
92 | This object is used to access a filtered version of a repository without | |
68 | altering the original repository object itself. We can not alter the |
|
93 | altering the original repository object itself. We can not alter the | |
69 | original object for two main reasons: |
|
94 | original object for two main reasons: | |
70 | - It prevents the use of a repo with multiple filters at the same time. In |
|
95 | - It prevents the use of a repo with multiple filters at the same time. In | |
71 | particular when multiple threads are involved. |
|
96 | particular when multiple threads are involved. | |
72 | - It makes scope of the filtering harder to control. |
|
97 | - It makes scope of the filtering harder to control. | |
73 |
|
98 | |||
74 | This object behaves very closely to the original repository. All attribute |
|
99 | This object behaves very closely to the original repository. All attribute | |
75 | operations are done on the original repository: |
|
100 | operations are done on the original repository: | |
76 | - An access to `repoview.someattr` actually returns `repo.someattr`, |
|
101 | - An access to `repoview.someattr` actually returns `repo.someattr`, | |
77 | - A write to `repoview.someattr` actually sets value of `repo.someattr`, |
|
102 | - A write to `repoview.someattr` actually sets value of `repo.someattr`, | |
78 | - A deletion of `repoview.someattr` actually drops `someattr` |
|
103 | - A deletion of `repoview.someattr` actually drops `someattr` | |
79 | from `repo.__dict__`. |
|
104 | from `repo.__dict__`. | |
80 |
|
105 | |||
81 | The only exception is the `changelog` property. It is overridden to return |
|
106 | The only exception is the `changelog` property. It is overridden to return | |
82 | a (surface) copy of `repo.changelog` with some revisions filtered. The |
|
107 | a (surface) copy of `repo.changelog` with some revisions filtered. The | |
83 | `filtername` attribute of the view control the revisions that need to be |
|
108 | `filtername` attribute of the view control the revisions that need to be | |
84 | filtered. (the fact the changelog is copied is an implementation detail). |
|
109 | filtered. (the fact the changelog is copied is an implementation detail). | |
85 |
|
110 | |||
86 | Unlike attributes, this object intercepts all method calls. This means that |
|
111 | Unlike attributes, this object intercepts all method calls. This means that | |
87 | all methods are run on the `repoview` object with the filtered `changelog` |
|
112 | all methods are run on the `repoview` object with the filtered `changelog` | |
88 | property. For this purpose the simple `repoview` class must be mixed with |
|
113 | property. For this purpose the simple `repoview` class must be mixed with | |
89 | the actual class of the repository. This ensures that the resulting |
|
114 | the actual class of the repository. This ensures that the resulting | |
90 | `repoview` object have the very same methods than the repo object. This |
|
115 | `repoview` object have the very same methods than the repo object. This | |
91 | leads to the property below. |
|
116 | leads to the property below. | |
92 |
|
117 | |||
93 | repoview.method() --> repo.__class__.method(repoview) |
|
118 | repoview.method() --> repo.__class__.method(repoview) | |
94 |
|
119 | |||
95 | The inheritance has to be done dynamically because `repo` can be of any |
|
120 | The inheritance has to be done dynamically because `repo` can be of any | |
96 | subclasses of `localrepo`. Eg: `bundlerepo` or `httprepo`. |
|
121 | subclasses of `localrepo`. Eg: `bundlerepo` or `httprepo`. | |
97 | """ |
|
122 | """ | |
98 |
|
123 | |||
99 | def __init__(self, repo, filtername): |
|
124 | def __init__(self, repo, filtername): | |
100 | object.__setattr__(self, '_unfilteredrepo', repo) |
|
125 | object.__setattr__(self, '_unfilteredrepo', repo) | |
101 | object.__setattr__(self, 'filtername', filtername) |
|
126 | object.__setattr__(self, 'filtername', filtername) | |
102 |
|
127 | |||
103 | # not a cacheproperty on purpose we shall implement a proper cache later |
|
128 | # not a cacheproperty on purpose we shall implement a proper cache later | |
104 | @property |
|
129 | @property | |
105 | def changelog(self): |
|
130 | def changelog(self): | |
106 | """return a filtered version of the changeset |
|
131 | """return a filtered version of the changeset | |
107 |
|
132 | |||
108 | this changelog must not be used for writing""" |
|
133 | this changelog must not be used for writing""" | |
109 | # some cache may be implemented later |
|
134 | # some cache may be implemented later | |
110 | cl = copy.copy(self._unfilteredrepo.changelog) |
|
135 | cl = copy.copy(self._unfilteredrepo.changelog) | |
111 | cl.filteredrevs = filteredrevs(self._unfilteredrepo, self.filtername) |
|
136 | cl.filteredrevs = filteredrevs(self._unfilteredrepo, self.filtername) | |
112 | return cl |
|
137 | return cl | |
113 |
|
138 | |||
114 | def unfiltered(self): |
|
139 | def unfiltered(self): | |
115 | """Return an unfiltered version of a repo""" |
|
140 | """Return an unfiltered version of a repo""" | |
116 | return self._unfilteredrepo |
|
141 | return self._unfilteredrepo | |
117 |
|
142 | |||
118 | def filtered(self, name): |
|
143 | def filtered(self, name): | |
119 | """Return a filtered version of a repository""" |
|
144 | """Return a filtered version of a repository""" | |
120 | if name == self.filtername: |
|
145 | if name == self.filtername: | |
121 | return self |
|
146 | return self | |
122 | return self.unfiltered().filtered(name) |
|
147 | return self.unfiltered().filtered(name) | |
123 |
|
148 | |||
124 | # everything access are forwarded to the proxied repo |
|
149 | # everything access are forwarded to the proxied repo | |
125 | def __getattr__(self, attr): |
|
150 | def __getattr__(self, attr): | |
126 | return getattr(self._unfilteredrepo, attr) |
|
151 | return getattr(self._unfilteredrepo, attr) | |
127 |
|
152 | |||
128 | def __setattr__(self, attr, value): |
|
153 | def __setattr__(self, attr, value): | |
129 | return setattr(self._unfilteredrepo, attr, value) |
|
154 | return setattr(self._unfilteredrepo, attr, value) | |
130 |
|
155 | |||
131 | def __delattr__(self, attr): |
|
156 | def __delattr__(self, attr): | |
132 | return delattr(self._unfilteredrepo, attr) |
|
157 | return delattr(self._unfilteredrepo, attr) | |
133 |
|
158 | |||
134 | # The `requirement` attribut is initialiazed during __init__. But |
|
159 | # The `requirement` attribut is initialiazed during __init__. But | |
135 | # __getattr__ won't be called as it also exists on the class. We need |
|
160 | # __getattr__ won't be called as it also exists on the class. We need | |
136 | # explicit forwarding to main repo here |
|
161 | # explicit forwarding to main repo here | |
137 | @property |
|
162 | @property | |
138 | def requirements(self): |
|
163 | def requirements(self): | |
139 | return self._unfilteredrepo.requirements |
|
164 | return self._unfilteredrepo.requirements | |
140 |
|
165 |
@@ -1,152 +1,152 | |||||
1 | test that new files created in .hg inherit the permissions from .hg/store |
|
1 | test that new files created in .hg inherit the permissions from .hg/store | |
2 |
|
2 | |||
3 |
|
3 | |||
4 | $ "$TESTDIR/hghave" unix-permissions || exit 80 |
|
4 | $ "$TESTDIR/hghave" unix-permissions || exit 80 | |
5 |
|
5 | |||
6 | $ mkdir dir |
|
6 | $ mkdir dir | |
7 |
|
7 | |||
8 | just in case somebody has a strange $TMPDIR |
|
8 | just in case somebody has a strange $TMPDIR | |
9 |
|
9 | |||
10 | $ chmod g-s dir |
|
10 | $ chmod g-s dir | |
11 | $ cd dir |
|
11 | $ cd dir | |
12 |
|
12 | |||
13 | $ cat >printmodes.py <<EOF |
|
13 | $ cat >printmodes.py <<EOF | |
14 | > import os, sys |
|
14 | > import os, sys | |
15 | > |
|
15 | > | |
16 | > allnames = [] |
|
16 | > allnames = [] | |
17 | > isdir = {} |
|
17 | > isdir = {} | |
18 | > for root, dirs, files in os.walk(sys.argv[1]): |
|
18 | > for root, dirs, files in os.walk(sys.argv[1]): | |
19 | > for d in dirs: |
|
19 | > for d in dirs: | |
20 | > name = os.path.join(root, d) |
|
20 | > name = os.path.join(root, d) | |
21 | > isdir[name] = 1 |
|
21 | > isdir[name] = 1 | |
22 | > allnames.append(name) |
|
22 | > allnames.append(name) | |
23 | > for f in files: |
|
23 | > for f in files: | |
24 | > name = os.path.join(root, f) |
|
24 | > name = os.path.join(root, f) | |
25 | > allnames.append(name) |
|
25 | > allnames.append(name) | |
26 | > allnames.sort() |
|
26 | > allnames.sort() | |
27 | > for name in allnames: |
|
27 | > for name in allnames: | |
28 | > suffix = name in isdir and '/' or '' |
|
28 | > suffix = name in isdir and '/' or '' | |
29 | > print '%05o %s%s' % (os.lstat(name).st_mode & 07777, name, suffix) |
|
29 | > print '%05o %s%s' % (os.lstat(name).st_mode & 07777, name, suffix) | |
30 | > EOF |
|
30 | > EOF | |
31 |
|
31 | |||
32 | $ cat >mode.py <<EOF |
|
32 | $ cat >mode.py <<EOF | |
33 | > import sys |
|
33 | > import sys | |
34 | > import os |
|
34 | > import os | |
35 | > print '%05o' % os.lstat(sys.argv[1]).st_mode |
|
35 | > print '%05o' % os.lstat(sys.argv[1]).st_mode | |
36 | > EOF |
|
36 | > EOF | |
37 |
|
37 | |||
38 | $ umask 077 |
|
38 | $ umask 077 | |
39 |
|
39 | |||
40 | $ hg init repo |
|
40 | $ hg init repo | |
41 | $ cd repo |
|
41 | $ cd repo | |
42 |
|
42 | |||
43 | $ chmod 0770 .hg/store |
|
43 | $ chmod 0770 .hg/store | |
44 |
|
44 | |||
45 | before commit |
|
45 | before commit | |
46 | store can be written by the group, other files cannot |
|
46 | store can be written by the group, other files cannot | |
47 | store is setgid |
|
47 | store is setgid | |
48 |
|
48 | |||
49 | $ python ../printmodes.py . |
|
49 | $ python ../printmodes.py . | |
50 | 00700 ./.hg/ |
|
50 | 00700 ./.hg/ | |
51 | 00600 ./.hg/00changelog.i |
|
51 | 00600 ./.hg/00changelog.i | |
52 | 00600 ./.hg/requires |
|
52 | 00600 ./.hg/requires | |
53 | 00770 ./.hg/store/ |
|
53 | 00770 ./.hg/store/ | |
54 |
|
54 | |||
55 | $ mkdir dir |
|
55 | $ mkdir dir | |
56 | $ touch foo dir/bar |
|
56 | $ touch foo dir/bar | |
57 | $ hg ci -qAm 'add files' |
|
57 | $ hg ci -qAm 'add files' | |
58 |
|
58 | |||
59 | after commit |
|
59 | after commit | |
60 | working dir files can only be written by the owner |
|
60 | working dir files can only be written by the owner | |
61 | files created in .hg can be written by the group |
|
61 | files created in .hg can be written by the group | |
62 | (in particular, store/**, dirstate, branch cache file, undo files) |
|
62 | (in particular, store/**, dirstate, branch cache file, undo files) | |
63 | new directories are setgid |
|
63 | new directories are setgid | |
64 |
|
64 | |||
65 | $ python ../printmodes.py . |
|
65 | $ python ../printmodes.py . | |
66 | 00700 ./.hg/ |
|
66 | 00700 ./.hg/ | |
67 | 00600 ./.hg/00changelog.i |
|
67 | 00600 ./.hg/00changelog.i | |
68 | 00770 ./.hg/cache/ |
|
68 | 00770 ./.hg/cache/ | |
69 | 00660 ./.hg/cache/branchheads-unserved |
|
69 | 00660 ./.hg/cache/branchheads-unserved | |
70 | 00660 ./.hg/dirstate |
|
70 | 00660 ./.hg/dirstate | |
71 | 00660 ./.hg/last-message.txt |
|
71 | 00660 ./.hg/last-message.txt | |
72 | 00600 ./.hg/requires |
|
72 | 00600 ./.hg/requires | |
73 | 00770 ./.hg/store/ |
|
73 | 00770 ./.hg/store/ | |
74 | 00660 ./.hg/store/00changelog.i |
|
74 | 00660 ./.hg/store/00changelog.i | |
75 | 00660 ./.hg/store/00manifest.i |
|
75 | 00660 ./.hg/store/00manifest.i | |
76 | 00770 ./.hg/store/data/ |
|
76 | 00770 ./.hg/store/data/ | |
77 | 00770 ./.hg/store/data/dir/ |
|
77 | 00770 ./.hg/store/data/dir/ | |
78 | 00660 ./.hg/store/data/dir/bar.i |
|
78 | 00660 ./.hg/store/data/dir/bar.i | |
79 | 00660 ./.hg/store/data/foo.i |
|
79 | 00660 ./.hg/store/data/foo.i | |
80 | 00660 ./.hg/store/fncache |
|
80 | 00660 ./.hg/store/fncache | |
81 | 00660 ./.hg/store/phaseroots |
|
81 | 00660 ./.hg/store/phaseroots | |
82 | 00660 ./.hg/store/undo |
|
82 | 00660 ./.hg/store/undo | |
83 | 00660 ./.hg/store/undo.phaseroots |
|
83 | 00660 ./.hg/store/undo.phaseroots | |
84 | 00660 ./.hg/undo.bookmarks |
|
84 | 00660 ./.hg/undo.bookmarks | |
85 | 00660 ./.hg/undo.branch |
|
85 | 00660 ./.hg/undo.branch | |
86 | 00660 ./.hg/undo.desc |
|
86 | 00660 ./.hg/undo.desc | |
87 | 00660 ./.hg/undo.dirstate |
|
87 | 00660 ./.hg/undo.dirstate | |
88 | 00700 ./dir/ |
|
88 | 00700 ./dir/ | |
89 | 00600 ./dir/bar |
|
89 | 00600 ./dir/bar | |
90 | 00600 ./foo |
|
90 | 00600 ./foo | |
91 |
|
91 | |||
92 | $ umask 007 |
|
92 | $ umask 007 | |
93 | $ hg init ../push |
|
93 | $ hg init ../push | |
94 |
|
94 | |||
95 | before push |
|
95 | before push | |
96 | group can write everything |
|
96 | group can write everything | |
97 |
|
97 | |||
98 | $ python ../printmodes.py ../push |
|
98 | $ python ../printmodes.py ../push | |
99 | 00770 ../push/.hg/ |
|
99 | 00770 ../push/.hg/ | |
100 | 00660 ../push/.hg/00changelog.i |
|
100 | 00660 ../push/.hg/00changelog.i | |
101 | 00660 ../push/.hg/requires |
|
101 | 00660 ../push/.hg/requires | |
102 | 00770 ../push/.hg/store/ |
|
102 | 00770 ../push/.hg/store/ | |
103 |
|
103 | |||
104 | $ umask 077 |
|
104 | $ umask 077 | |
105 | $ hg -q push ../push |
|
105 | $ hg -q push ../push | |
106 |
|
106 | |||
107 | after push |
|
107 | after push | |
108 | group can still write everything |
|
108 | group can still write everything | |
109 |
|
109 | |||
110 | $ python ../printmodes.py ../push |
|
110 | $ python ../printmodes.py ../push | |
111 | 00770 ../push/.hg/ |
|
111 | 00770 ../push/.hg/ | |
112 | 00660 ../push/.hg/00changelog.i |
|
112 | 00660 ../push/.hg/00changelog.i | |
113 | 00770 ../push/.hg/cache/ |
|
113 | 00770 ../push/.hg/cache/ | |
114 |
00660 ../push/.hg/cache/branchheads- |
|
114 | 00660 ../push/.hg/cache/branchheads-impactable | |
115 | 00660 ../push/.hg/requires |
|
115 | 00660 ../push/.hg/requires | |
116 | 00770 ../push/.hg/store/ |
|
116 | 00770 ../push/.hg/store/ | |
117 | 00660 ../push/.hg/store/00changelog.i |
|
117 | 00660 ../push/.hg/store/00changelog.i | |
118 | 00660 ../push/.hg/store/00manifest.i |
|
118 | 00660 ../push/.hg/store/00manifest.i | |
119 | 00770 ../push/.hg/store/data/ |
|
119 | 00770 ../push/.hg/store/data/ | |
120 | 00770 ../push/.hg/store/data/dir/ |
|
120 | 00770 ../push/.hg/store/data/dir/ | |
121 | 00660 ../push/.hg/store/data/dir/bar.i |
|
121 | 00660 ../push/.hg/store/data/dir/bar.i | |
122 | 00660 ../push/.hg/store/data/foo.i |
|
122 | 00660 ../push/.hg/store/data/foo.i | |
123 | 00660 ../push/.hg/store/fncache |
|
123 | 00660 ../push/.hg/store/fncache | |
124 | 00660 ../push/.hg/store/phaseroots |
|
124 | 00660 ../push/.hg/store/phaseroots | |
125 | 00660 ../push/.hg/store/undo |
|
125 | 00660 ../push/.hg/store/undo | |
126 | 00660 ../push/.hg/store/undo.phaseroots |
|
126 | 00660 ../push/.hg/store/undo.phaseroots | |
127 | 00660 ../push/.hg/undo.bookmarks |
|
127 | 00660 ../push/.hg/undo.bookmarks | |
128 | 00660 ../push/.hg/undo.branch |
|
128 | 00660 ../push/.hg/undo.branch | |
129 | 00660 ../push/.hg/undo.desc |
|
129 | 00660 ../push/.hg/undo.desc | |
130 | 00660 ../push/.hg/undo.dirstate |
|
130 | 00660 ../push/.hg/undo.dirstate | |
131 |
|
131 | |||
132 |
|
132 | |||
133 | Test that we don't lose the setgid bit when we call chmod. |
|
133 | Test that we don't lose the setgid bit when we call chmod. | |
134 | Not all systems support setgid directories (e.g. HFS+), so |
|
134 | Not all systems support setgid directories (e.g. HFS+), so | |
135 | just check that directories have the same mode. |
|
135 | just check that directories have the same mode. | |
136 |
|
136 | |||
137 | $ cd .. |
|
137 | $ cd .. | |
138 | $ hg init setgid |
|
138 | $ hg init setgid | |
139 | $ cd setgid |
|
139 | $ cd setgid | |
140 | $ chmod g+rwx .hg/store |
|
140 | $ chmod g+rwx .hg/store | |
141 | $ chmod g+s .hg/store 2> /dev/null || true |
|
141 | $ chmod g+s .hg/store 2> /dev/null || true | |
142 | $ mkdir dir |
|
142 | $ mkdir dir | |
143 | $ touch dir/file |
|
143 | $ touch dir/file | |
144 | $ hg ci -qAm 'add dir/file' |
|
144 | $ hg ci -qAm 'add dir/file' | |
145 | $ storemode=`python ../mode.py .hg/store` |
|
145 | $ storemode=`python ../mode.py .hg/store` | |
146 | $ dirmode=`python ../mode.py .hg/store/data/dir` |
|
146 | $ dirmode=`python ../mode.py .hg/store/data/dir` | |
147 | $ if [ "$storemode" != "$dirmode" ]; then |
|
147 | $ if [ "$storemode" != "$dirmode" ]; then | |
148 | > echo "$storemode != $dirmode" |
|
148 | > echo "$storemode != $dirmode" | |
149 | > fi |
|
149 | > fi | |
150 | $ cd .. |
|
150 | $ cd .. | |
151 |
|
151 | |||
152 | $ cd .. # g-s dir |
|
152 | $ cd .. # g-s dir |
@@ -1,345 +1,345 | |||||
1 | $ branchcache=.hg/cache/branchheads |
|
1 | $ branchcache=.hg/cache/branchheads | |
2 |
|
2 | |||
3 | $ listbranchcaches() { |
|
3 | $ listbranchcaches() { | |
4 | > for f in .hg/cache/branchheads*; |
|
4 | > for f in .hg/cache/branchheads*; | |
5 | > do echo === $f ===; |
|
5 | > do echo === $f ===; | |
6 | > cat $f; |
|
6 | > cat $f; | |
7 | > done; |
|
7 | > done; | |
8 | > } |
|
8 | > } | |
9 | $ purgebranchcaches() { |
|
9 | $ purgebranchcaches() { | |
10 | > rm .hg/cache/branchheads* |
|
10 | > rm .hg/cache/branchheads* | |
11 | > } |
|
11 | > } | |
12 |
|
12 | |||
13 | $ hg init t |
|
13 | $ hg init t | |
14 | $ cd t |
|
14 | $ cd t | |
15 |
|
15 | |||
16 | $ hg branches |
|
16 | $ hg branches | |
17 | $ echo foo > a |
|
17 | $ echo foo > a | |
18 | $ hg add a |
|
18 | $ hg add a | |
19 | $ hg ci -m "initial" |
|
19 | $ hg ci -m "initial" | |
20 | $ hg branch foo |
|
20 | $ hg branch foo | |
21 | marked working directory as branch foo |
|
21 | marked working directory as branch foo | |
22 | (branches are permanent and global, did you want a bookmark?) |
|
22 | (branches are permanent and global, did you want a bookmark?) | |
23 | $ hg branch |
|
23 | $ hg branch | |
24 | foo |
|
24 | foo | |
25 | $ hg ci -m "add branch name" |
|
25 | $ hg ci -m "add branch name" | |
26 | $ hg branch bar |
|
26 | $ hg branch bar | |
27 | marked working directory as branch bar |
|
27 | marked working directory as branch bar | |
28 | (branches are permanent and global, did you want a bookmark?) |
|
28 | (branches are permanent and global, did you want a bookmark?) | |
29 | $ hg ci -m "change branch name" |
|
29 | $ hg ci -m "change branch name" | |
30 |
|
30 | |||
31 | Branch shadowing: |
|
31 | Branch shadowing: | |
32 |
|
32 | |||
33 | $ hg branch default |
|
33 | $ hg branch default | |
34 | abort: a branch of the same name already exists |
|
34 | abort: a branch of the same name already exists | |
35 | (use 'hg update' to switch to it) |
|
35 | (use 'hg update' to switch to it) | |
36 | [255] |
|
36 | [255] | |
37 |
|
37 | |||
38 | $ hg branch -f default |
|
38 | $ hg branch -f default | |
39 | marked working directory as branch default |
|
39 | marked working directory as branch default | |
40 | (branches are permanent and global, did you want a bookmark?) |
|
40 | (branches are permanent and global, did you want a bookmark?) | |
41 |
|
41 | |||
42 | $ hg ci -m "clear branch name" |
|
42 | $ hg ci -m "clear branch name" | |
43 | created new head |
|
43 | created new head | |
44 |
|
44 | |||
45 | There should be only one default branch head |
|
45 | There should be only one default branch head | |
46 |
|
46 | |||
47 | $ hg heads . |
|
47 | $ hg heads . | |
48 | changeset: 3:1c28f494dae6 |
|
48 | changeset: 3:1c28f494dae6 | |
49 | tag: tip |
|
49 | tag: tip | |
50 | user: test |
|
50 | user: test | |
51 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
51 | date: Thu Jan 01 00:00:00 1970 +0000 | |
52 | summary: clear branch name |
|
52 | summary: clear branch name | |
53 |
|
53 | |||
54 |
|
54 | |||
55 | $ hg co foo |
|
55 | $ hg co foo | |
56 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
56 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
57 | $ hg branch |
|
57 | $ hg branch | |
58 | foo |
|
58 | foo | |
59 | $ echo bleah > a |
|
59 | $ echo bleah > a | |
60 | $ hg ci -m "modify a branch" |
|
60 | $ hg ci -m "modify a branch" | |
61 |
|
61 | |||
62 | $ hg merge default |
|
62 | $ hg merge default | |
63 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
63 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
64 | (branch merge, don't forget to commit) |
|
64 | (branch merge, don't forget to commit) | |
65 |
|
65 | |||
66 | $ hg branch |
|
66 | $ hg branch | |
67 | foo |
|
67 | foo | |
68 | $ hg ci -m "merge" |
|
68 | $ hg ci -m "merge" | |
69 |
|
69 | |||
70 | $ hg log |
|
70 | $ hg log | |
71 | changeset: 5:530046499edf |
|
71 | changeset: 5:530046499edf | |
72 | branch: foo |
|
72 | branch: foo | |
73 | tag: tip |
|
73 | tag: tip | |
74 | parent: 4:adf1a74a7f7b |
|
74 | parent: 4:adf1a74a7f7b | |
75 | parent: 3:1c28f494dae6 |
|
75 | parent: 3:1c28f494dae6 | |
76 | user: test |
|
76 | user: test | |
77 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
77 | date: Thu Jan 01 00:00:00 1970 +0000 | |
78 | summary: merge |
|
78 | summary: merge | |
79 |
|
79 | |||
80 | changeset: 4:adf1a74a7f7b |
|
80 | changeset: 4:adf1a74a7f7b | |
81 | branch: foo |
|
81 | branch: foo | |
82 | parent: 1:6c0e42da283a |
|
82 | parent: 1:6c0e42da283a | |
83 | user: test |
|
83 | user: test | |
84 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
84 | date: Thu Jan 01 00:00:00 1970 +0000 | |
85 | summary: modify a branch |
|
85 | summary: modify a branch | |
86 |
|
86 | |||
87 | changeset: 3:1c28f494dae6 |
|
87 | changeset: 3:1c28f494dae6 | |
88 | user: test |
|
88 | user: test | |
89 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
89 | date: Thu Jan 01 00:00:00 1970 +0000 | |
90 | summary: clear branch name |
|
90 | summary: clear branch name | |
91 |
|
91 | |||
92 | changeset: 2:c21617b13b22 |
|
92 | changeset: 2:c21617b13b22 | |
93 | branch: bar |
|
93 | branch: bar | |
94 | user: test |
|
94 | user: test | |
95 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
95 | date: Thu Jan 01 00:00:00 1970 +0000 | |
96 | summary: change branch name |
|
96 | summary: change branch name | |
97 |
|
97 | |||
98 | changeset: 1:6c0e42da283a |
|
98 | changeset: 1:6c0e42da283a | |
99 | branch: foo |
|
99 | branch: foo | |
100 | user: test |
|
100 | user: test | |
101 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
101 | date: Thu Jan 01 00:00:00 1970 +0000 | |
102 | summary: add branch name |
|
102 | summary: add branch name | |
103 |
|
103 | |||
104 | changeset: 0:db01e8ea3388 |
|
104 | changeset: 0:db01e8ea3388 | |
105 | user: test |
|
105 | user: test | |
106 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
106 | date: Thu Jan 01 00:00:00 1970 +0000 | |
107 | summary: initial |
|
107 | summary: initial | |
108 |
|
108 | |||
109 | $ hg branches |
|
109 | $ hg branches | |
110 | foo 5:530046499edf |
|
110 | foo 5:530046499edf | |
111 | default 3:1c28f494dae6 (inactive) |
|
111 | default 3:1c28f494dae6 (inactive) | |
112 | bar 2:c21617b13b22 (inactive) |
|
112 | bar 2:c21617b13b22 (inactive) | |
113 |
|
113 | |||
114 | $ hg branches -q |
|
114 | $ hg branches -q | |
115 | foo |
|
115 | foo | |
116 | default |
|
116 | default | |
117 | bar |
|
117 | bar | |
118 |
|
118 | |||
119 | Test for invalid branch cache: |
|
119 | Test for invalid branch cache: | |
120 |
|
120 | |||
121 | $ hg rollback |
|
121 | $ hg rollback | |
122 | repository tip rolled back to revision 4 (undo commit) |
|
122 | repository tip rolled back to revision 4 (undo commit) | |
123 | working directory now based on revisions 4 and 3 |
|
123 | working directory now based on revisions 4 and 3 | |
124 |
|
124 | |||
125 | $ cp ${branchcache}-unserved .hg/bc-invalid |
|
125 | $ cp ${branchcache}-unserved .hg/bc-invalid | |
126 |
|
126 | |||
127 | $ hg log -r foo |
|
127 | $ hg log -r foo | |
128 | changeset: 4:adf1a74a7f7b |
|
128 | changeset: 4:adf1a74a7f7b | |
129 | branch: foo |
|
129 | branch: foo | |
130 | tag: tip |
|
130 | tag: tip | |
131 | parent: 1:6c0e42da283a |
|
131 | parent: 1:6c0e42da283a | |
132 | user: test |
|
132 | user: test | |
133 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
133 | date: Thu Jan 01 00:00:00 1970 +0000 | |
134 | summary: modify a branch |
|
134 | summary: modify a branch | |
135 |
|
135 | |||
136 | $ cp .hg/bc-invalid $branchcache |
|
136 | $ cp .hg/bc-invalid $branchcache | |
137 |
|
137 | |||
138 | $ hg --debug log -r foo |
|
138 | $ hg --debug log -r foo | |
139 | invalid branchheads cache: tip differs |
|
139 | invalid branchheads cache: tip differs | |
140 | changeset: 4:adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 |
|
140 | changeset: 4:adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 | |
141 | branch: foo |
|
141 | branch: foo | |
142 | tag: tip |
|
142 | tag: tip | |
143 | phase: draft |
|
143 | phase: draft | |
144 | parent: 1:6c0e42da283a56b5edc5b4fadb491365ec7f5fa8 |
|
144 | parent: 1:6c0e42da283a56b5edc5b4fadb491365ec7f5fa8 | |
145 | parent: -1:0000000000000000000000000000000000000000 |
|
145 | parent: -1:0000000000000000000000000000000000000000 | |
146 | manifest: 1:8c342a37dfba0b3d3ce073562a00d8a813c54ffe |
|
146 | manifest: 1:8c342a37dfba0b3d3ce073562a00d8a813c54ffe | |
147 | user: test |
|
147 | user: test | |
148 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
148 | date: Thu Jan 01 00:00:00 1970 +0000 | |
149 | files: a |
|
149 | files: a | |
150 | extra: branch=foo |
|
150 | extra: branch=foo | |
151 | description: |
|
151 | description: | |
152 | modify a branch |
|
152 | modify a branch | |
153 |
|
153 | |||
154 |
|
154 | |||
155 | $ purgebranchcaches |
|
155 | $ purgebranchcaches | |
156 | $ echo corrupted > $branchcache |
|
156 | $ echo corrupted > $branchcache | |
157 |
|
157 | |||
158 | $ hg log -qr foo |
|
158 | $ hg log -qr foo | |
159 | 4:adf1a74a7f7b |
|
159 | 4:adf1a74a7f7b | |
160 |
|
160 | |||
161 | $ listbranchcaches |
|
161 | $ listbranchcaches | |
162 | === .hg/cache/branchheads === |
|
162 | === .hg/cache/branchheads === | |
163 | corrupted |
|
163 | corrupted | |
164 | === .hg/cache/branchheads-unserved === |
|
164 | === .hg/cache/branchheads-unserved === | |
165 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4 |
|
165 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4 | |
166 | 1c28f494dae69a2f8fc815059d257eccf3fcfe75 default |
|
166 | 1c28f494dae69a2f8fc815059d257eccf3fcfe75 default | |
167 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo |
|
167 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo | |
168 | c21617b13b220988e7a2e26290fbe4325ffa7139 bar |
|
168 | c21617b13b220988e7a2e26290fbe4325ffa7139 bar | |
169 |
|
169 | |||
170 | Push should update the branch cache: |
|
170 | Push should update the branch cache: | |
171 |
|
171 | |||
172 | $ hg init ../target |
|
172 | $ hg init ../target | |
173 |
|
173 | |||
174 | Pushing just rev 0: |
|
174 | Pushing just rev 0: | |
175 |
|
175 | |||
176 | $ hg push -qr 0 ../target |
|
176 | $ hg push -qr 0 ../target | |
177 |
|
177 | |||
178 | $ (cd ../target/; listbranchcaches) |
|
178 | $ (cd ../target/; listbranchcaches) | |
179 |
=== .hg/cache/branchheads- |
|
179 | === .hg/cache/branchheads-impactable === | |
180 | db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0 |
|
180 | db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0 | |
181 | db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default |
|
181 | db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default | |
182 |
|
182 | |||
183 | Pushing everything: |
|
183 | Pushing everything: | |
184 |
|
184 | |||
185 | $ hg push -qf ../target |
|
185 | $ hg push -qf ../target | |
186 |
|
186 | |||
187 | $ (cd ../target/; listbranchcaches) |
|
187 | $ (cd ../target/; listbranchcaches) | |
188 |
=== .hg/cache/branchheads- |
|
188 | === .hg/cache/branchheads-impactable === | |
189 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4 |
|
189 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4 | |
190 | 1c28f494dae69a2f8fc815059d257eccf3fcfe75 default |
|
190 | 1c28f494dae69a2f8fc815059d257eccf3fcfe75 default | |
191 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo |
|
191 | adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo | |
192 | c21617b13b220988e7a2e26290fbe4325ffa7139 bar |
|
192 | c21617b13b220988e7a2e26290fbe4325ffa7139 bar | |
193 |
|
193 | |||
194 | Update with no arguments: tipmost revision of the current branch: |
|
194 | Update with no arguments: tipmost revision of the current branch: | |
195 |
|
195 | |||
196 | $ hg up -q -C 0 |
|
196 | $ hg up -q -C 0 | |
197 | $ hg up -q |
|
197 | $ hg up -q | |
198 | $ hg id |
|
198 | $ hg id | |
199 | 1c28f494dae6 |
|
199 | 1c28f494dae6 | |
200 |
|
200 | |||
201 | $ hg up -q 1 |
|
201 | $ hg up -q 1 | |
202 | $ hg up -q |
|
202 | $ hg up -q | |
203 | $ hg id |
|
203 | $ hg id | |
204 | adf1a74a7f7b (foo) tip |
|
204 | adf1a74a7f7b (foo) tip | |
205 |
|
205 | |||
206 | $ hg branch foobar |
|
206 | $ hg branch foobar | |
207 | marked working directory as branch foobar |
|
207 | marked working directory as branch foobar | |
208 | (branches are permanent and global, did you want a bookmark?) |
|
208 | (branches are permanent and global, did you want a bookmark?) | |
209 |
|
209 | |||
210 | $ hg up |
|
210 | $ hg up | |
211 | abort: branch foobar not found |
|
211 | abort: branch foobar not found | |
212 | [255] |
|
212 | [255] | |
213 |
|
213 | |||
214 | Fastforward merge: |
|
214 | Fastforward merge: | |
215 |
|
215 | |||
216 | $ hg branch ff |
|
216 | $ hg branch ff | |
217 | marked working directory as branch ff |
|
217 | marked working directory as branch ff | |
218 | (branches are permanent and global, did you want a bookmark?) |
|
218 | (branches are permanent and global, did you want a bookmark?) | |
219 |
|
219 | |||
220 | $ echo ff > ff |
|
220 | $ echo ff > ff | |
221 | $ hg ci -Am'fast forward' |
|
221 | $ hg ci -Am'fast forward' | |
222 | adding ff |
|
222 | adding ff | |
223 |
|
223 | |||
224 | $ hg up foo |
|
224 | $ hg up foo | |
225 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
225 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
226 |
|
226 | |||
227 | $ hg merge ff |
|
227 | $ hg merge ff | |
228 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
228 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
229 | (branch merge, don't forget to commit) |
|
229 | (branch merge, don't forget to commit) | |
230 |
|
230 | |||
231 | $ hg branch |
|
231 | $ hg branch | |
232 | foo |
|
232 | foo | |
233 | $ hg commit -m'Merge ff into foo' |
|
233 | $ hg commit -m'Merge ff into foo' | |
234 | $ hg parents |
|
234 | $ hg parents | |
235 | changeset: 6:185ffbfefa30 |
|
235 | changeset: 6:185ffbfefa30 | |
236 | branch: foo |
|
236 | branch: foo | |
237 | tag: tip |
|
237 | tag: tip | |
238 | parent: 4:adf1a74a7f7b |
|
238 | parent: 4:adf1a74a7f7b | |
239 | parent: 5:1a3c27dc5e11 |
|
239 | parent: 5:1a3c27dc5e11 | |
240 | user: test |
|
240 | user: test | |
241 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
241 | date: Thu Jan 01 00:00:00 1970 +0000 | |
242 | summary: Merge ff into foo |
|
242 | summary: Merge ff into foo | |
243 |
|
243 | |||
244 | $ hg manifest |
|
244 | $ hg manifest | |
245 | a |
|
245 | a | |
246 | ff |
|
246 | ff | |
247 |
|
247 | |||
248 |
|
248 | |||
249 | Test merging, add 3 default heads and one test head: |
|
249 | Test merging, add 3 default heads and one test head: | |
250 |
|
250 | |||
251 | $ cd .. |
|
251 | $ cd .. | |
252 | $ hg init merges |
|
252 | $ hg init merges | |
253 | $ cd merges |
|
253 | $ cd merges | |
254 | $ echo a > a |
|
254 | $ echo a > a | |
255 | $ hg ci -Ama |
|
255 | $ hg ci -Ama | |
256 | adding a |
|
256 | adding a | |
257 |
|
257 | |||
258 | $ echo b > b |
|
258 | $ echo b > b | |
259 | $ hg ci -Amb |
|
259 | $ hg ci -Amb | |
260 | adding b |
|
260 | adding b | |
261 |
|
261 | |||
262 | $ hg up 0 |
|
262 | $ hg up 0 | |
263 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
263 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
264 | $ echo c > c |
|
264 | $ echo c > c | |
265 | $ hg ci -Amc |
|
265 | $ hg ci -Amc | |
266 | adding c |
|
266 | adding c | |
267 | created new head |
|
267 | created new head | |
268 |
|
268 | |||
269 | $ hg up 0 |
|
269 | $ hg up 0 | |
270 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
270 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
271 | $ echo d > d |
|
271 | $ echo d > d | |
272 | $ hg ci -Amd |
|
272 | $ hg ci -Amd | |
273 | adding d |
|
273 | adding d | |
274 | created new head |
|
274 | created new head | |
275 |
|
275 | |||
276 | $ hg up 0 |
|
276 | $ hg up 0 | |
277 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
277 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
278 | $ hg branch test |
|
278 | $ hg branch test | |
279 | marked working directory as branch test |
|
279 | marked working directory as branch test | |
280 | (branches are permanent and global, did you want a bookmark?) |
|
280 | (branches are permanent and global, did you want a bookmark?) | |
281 | $ echo e >> e |
|
281 | $ echo e >> e | |
282 | $ hg ci -Ame |
|
282 | $ hg ci -Ame | |
283 | adding e |
|
283 | adding e | |
284 |
|
284 | |||
285 | $ hg log |
|
285 | $ hg log | |
286 | changeset: 4:3a1e01ed1df4 |
|
286 | changeset: 4:3a1e01ed1df4 | |
287 | branch: test |
|
287 | branch: test | |
288 | tag: tip |
|
288 | tag: tip | |
289 | parent: 0:cb9a9f314b8b |
|
289 | parent: 0:cb9a9f314b8b | |
290 | user: test |
|
290 | user: test | |
291 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
291 | date: Thu Jan 01 00:00:00 1970 +0000 | |
292 | summary: e |
|
292 | summary: e | |
293 |
|
293 | |||
294 | changeset: 3:980f7dc84c29 |
|
294 | changeset: 3:980f7dc84c29 | |
295 | parent: 0:cb9a9f314b8b |
|
295 | parent: 0:cb9a9f314b8b | |
296 | user: test |
|
296 | user: test | |
297 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
297 | date: Thu Jan 01 00:00:00 1970 +0000 | |
298 | summary: d |
|
298 | summary: d | |
299 |
|
299 | |||
300 | changeset: 2:d36c0562f908 |
|
300 | changeset: 2:d36c0562f908 | |
301 | parent: 0:cb9a9f314b8b |
|
301 | parent: 0:cb9a9f314b8b | |
302 | user: test |
|
302 | user: test | |
303 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
303 | date: Thu Jan 01 00:00:00 1970 +0000 | |
304 | summary: c |
|
304 | summary: c | |
305 |
|
305 | |||
306 | changeset: 1:d2ae7f538514 |
|
306 | changeset: 1:d2ae7f538514 | |
307 | user: test |
|
307 | user: test | |
308 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
308 | date: Thu Jan 01 00:00:00 1970 +0000 | |
309 | summary: b |
|
309 | summary: b | |
310 |
|
310 | |||
311 | changeset: 0:cb9a9f314b8b |
|
311 | changeset: 0:cb9a9f314b8b | |
312 | user: test |
|
312 | user: test | |
313 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
313 | date: Thu Jan 01 00:00:00 1970 +0000 | |
314 | summary: a |
|
314 | summary: a | |
315 |
|
315 | |||
316 | Implicit merge with test branch as parent: |
|
316 | Implicit merge with test branch as parent: | |
317 |
|
317 | |||
318 | $ hg merge |
|
318 | $ hg merge | |
319 | abort: branch 'test' has one head - please merge with an explicit rev |
|
319 | abort: branch 'test' has one head - please merge with an explicit rev | |
320 | (run 'hg heads' to see all heads) |
|
320 | (run 'hg heads' to see all heads) | |
321 | [255] |
|
321 | [255] | |
322 | $ hg up -C default |
|
322 | $ hg up -C default | |
323 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
323 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
324 |
|
324 | |||
325 | Implicit merge with default branch as parent: |
|
325 | Implicit merge with default branch as parent: | |
326 |
|
326 | |||
327 | $ hg merge |
|
327 | $ hg merge | |
328 | abort: branch 'default' has 3 heads - please merge with an explicit rev |
|
328 | abort: branch 'default' has 3 heads - please merge with an explicit rev | |
329 | (run 'hg heads .' to see heads) |
|
329 | (run 'hg heads .' to see heads) | |
330 | [255] |
|
330 | [255] | |
331 |
|
331 | |||
332 | 3 branch heads, explicit merge required: |
|
332 | 3 branch heads, explicit merge required: | |
333 |
|
333 | |||
334 | $ hg merge 2 |
|
334 | $ hg merge 2 | |
335 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
335 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
336 | (branch merge, don't forget to commit) |
|
336 | (branch merge, don't forget to commit) | |
337 | $ hg ci -m merge |
|
337 | $ hg ci -m merge | |
338 |
|
338 | |||
339 | 2 branch heads, implicit merge works: |
|
339 | 2 branch heads, implicit merge works: | |
340 |
|
340 | |||
341 | $ hg merge |
|
341 | $ hg merge | |
342 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
342 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
343 | (branch merge, don't forget to commit) |
|
343 | (branch merge, don't forget to commit) | |
344 |
|
344 | |||
345 | $ cd .. |
|
345 | $ cd .. |
General Comments 0
You need to be logged in to leave comments.
Login now