##// END OF EJS Templates
clfilter: add impactable filter...
Pierre-Yves David -
r18246:58ca19ed default
parent child Browse files
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-mutable
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-mutable ===
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-mutable ===
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