Show More
@@ -125,6 +125,10 b' def extsetup(ui):' | |||
|
125 | 125 | |
|
126 | 126 | def _hassharedbookmarks(repo): |
|
127 | 127 | """Returns whether this repo has shared bookmarks""" |
|
128 | if bookmarks.bookmarksinstore(repo): | |
|
129 | # Kind of a lie, but it means that we skip our custom reads and writes | |
|
130 | # from/to the source repo. | |
|
131 | return False | |
|
128 | 132 | try: |
|
129 | 133 | shared = repo.vfs.read('shared').splitlines() |
|
130 | 134 | except IOError as inst: |
@@ -33,6 +33,14 b' from . import (' | |||
|
33 | 33 | # custom styles |
|
34 | 34 | activebookmarklabel = 'bookmarks.active bookmarks.current' |
|
35 | 35 | |
|
36 | BOOKMARKS_IN_STORE_REQUIREMENT = 'bookmarksinstore' | |
|
37 | ||
|
38 | def bookmarksinstore(repo): | |
|
39 | return BOOKMARKS_IN_STORE_REQUIREMENT in repo.requirements | |
|
40 | ||
|
41 | def bookmarksvfs(repo): | |
|
42 | return repo.svfs if bookmarksinstore(repo) else repo.vfs | |
|
43 | ||
|
36 | 44 | def _getbkfile(repo): |
|
37 | 45 | """Hook so that extensions that mess with the store can hook bm storage. |
|
38 | 46 | |
@@ -40,7 +48,7 b' def _getbkfile(repo):' | |||
|
40 | 48 | bookmarks or the committed ones. Other extensions (like share) |
|
41 | 49 | may need to tweak this behavior further. |
|
42 | 50 | """ |
|
43 |
fp, pending = txnutil.trypending(repo.root, repo |
|
|
51 | fp, pending = txnutil.trypending(repo.root, bookmarksvfs(repo), 'bookmarks') | |
|
44 | 52 | return fp |
|
45 | 53 | |
|
46 | 54 | class bmstore(object): |
@@ -91,8 +99,11 b' class bmstore(object):' | |||
|
91 | 99 | # ValueError: |
|
92 | 100 | # - node in nm, for non-20-bytes entry |
|
93 | 101 | # - split(...), for string without ' ' |
|
94 |
|
|
|
95 |
|
|
|
102 | bookmarkspath = '.hg/bookmarks' | |
|
103 | if bookmarksinstore(repo): | |
|
104 | bookmarkspath = '.hg/store/bookmarks' | |
|
105 | repo.ui.warn(_('malformed line in %s: %r\n') | |
|
106 | % (bookmarkspath, pycompat.bytestr(line))) | |
|
96 | 107 | except IOError as inst: |
|
97 | 108 | if inst.errno != errno.ENOENT: |
|
98 | 109 | raise |
@@ -192,8 +203,9 b' class bmstore(object):' | |||
|
192 | 203 | """record that bookmarks have been changed in a transaction |
|
193 | 204 | |
|
194 | 205 | The transaction is then responsible for updating the file content.""" |
|
206 | location = '' if bookmarksinstore(self._repo) else 'plain' | |
|
195 | 207 | tr.addfilegenerator('bookmarks', ('bookmarks',), self._write, |
|
196 |
location= |
|
|
208 | location=location) | |
|
197 | 209 | tr.hookargs['bookmark_moved'] = '1' |
|
198 | 210 | |
|
199 | 211 | def _writerepo(self, repo): |
@@ -203,9 +215,14 b' class bmstore(object):' | |||
|
203 | 215 | rbm.active = None |
|
204 | 216 | rbm._writeactive() |
|
205 | 217 | |
|
206 | with repo.wlock(): | |
|
207 | with repo.vfs('bookmarks', 'w', atomictemp=True, | |
|
208 | checkambig=True) as f: | |
|
218 | if bookmarksinstore(repo): | |
|
219 | vfs = repo.svfs | |
|
220 | lock = repo.lock() | |
|
221 | else: | |
|
222 | vfs = repo.vfs | |
|
223 | lock = repo.wlock() | |
|
224 | with lock: | |
|
225 | with vfs('bookmarks', 'w', atomictemp=True, checkambig=True) as f: | |
|
209 | 226 | self._write(f) |
|
210 | 227 | |
|
211 | 228 | def _writeactive(self): |
@@ -428,7 +445,11 b' def listbookmarks(repo):' | |||
|
428 | 445 | return d |
|
429 | 446 | |
|
430 | 447 | def pushbookmark(repo, key, old, new): |
|
431 | with repo.wlock(), repo.lock(), repo.transaction('bookmarks') as tr: | |
|
448 | if bookmarksinstore(repo): | |
|
449 | wlock = util.nullcontextmanager() | |
|
450 | else: | |
|
451 | wlock = repo.wlock() | |
|
452 | with wlock, repo.lock(), repo.transaction('bookmarks') as tr: | |
|
432 | 453 | marks = repo._bookmarks |
|
433 | 454 | existing = hex(marks.get(key, '')) |
|
434 | 455 | if existing != old and existing != new: |
@@ -676,6 +676,9 b" coreconfigitem('extdata', '.*'," | |||
|
676 | 676 | default=None, |
|
677 | 677 | generic=True, |
|
678 | 678 | ) |
|
679 | coreconfigitem('format', 'bookmarks-in-store', | |
|
680 | default=False, | |
|
681 | ) | |
|
679 | 682 | coreconfigitem('format', 'chunkcachesize', |
|
680 | 683 | default=None, |
|
681 | 684 | ) |
@@ -879,6 +879,15 b' https://www.mercurial-scm.org/wiki/Missi' | |||
|
879 | 879 | |
|
880 | 880 | On some system, Mercurial installation may lack `zstd` supports. Default is `zlib`. |
|
881 | 881 | |
|
882 | ``bookmarks-in-store`` | |
|
883 | Store bookmarks in .hg/store/. This means that bookmarks are shared when | |
|
884 | using `hg share` regardless of the `-B` option. | |
|
885 | ||
|
886 | Repositories with this on-disk format require Mercurial version 5.1. | |
|
887 | ||
|
888 | Disabled by default. | |
|
889 | ||
|
890 | ||
|
882 | 891 | ``graph`` |
|
883 | 892 | --------- |
|
884 | 893 |
@@ -122,6 +122,25 b' class storecache(_basefilecache):' | |||
|
122 | 122 | def join(self, obj, fname): |
|
123 | 123 | return obj.sjoin(fname) |
|
124 | 124 | |
|
125 | class mixedrepostorecache(_basefilecache): | |
|
126 | """filecache for a mix files in .hg/store and outside""" | |
|
127 | def __init__(self, *pathsandlocations): | |
|
128 | # scmutil.filecache only uses the path for passing back into our | |
|
129 | # join(), so we can safely pass a list of paths and locations | |
|
130 | super(mixedrepostorecache, self).__init__(*pathsandlocations) | |
|
131 | for path, location in pathsandlocations: | |
|
132 | _cachedfiles.update(pathsandlocations) | |
|
133 | ||
|
134 | def join(self, obj, fnameandlocation): | |
|
135 | fname, location = fnameandlocation | |
|
136 | if location == '': | |
|
137 | return obj.vfs.join(fname) | |
|
138 | else: | |
|
139 | if location != 'store': | |
|
140 | raise error.ProgrammingError('unexpected location: %s' % | |
|
141 | location) | |
|
142 | return obj.sjoin(fname) | |
|
143 | ||
|
125 | 144 | def isfilecached(repo, name): |
|
126 | 145 | """check if a repo has already cached "name" filecache-ed property |
|
127 | 146 | |
@@ -891,6 +910,7 b' class localrepository(object):' | |||
|
891 | 910 | 'treemanifest', |
|
892 | 911 | REVLOGV2_REQUIREMENT, |
|
893 | 912 | SPARSEREVLOG_REQUIREMENT, |
|
913 | bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT, | |
|
894 | 914 | } |
|
895 | 915 | _basesupported = supportedformats | { |
|
896 | 916 | 'store', |
@@ -1205,7 +1225,8 b' class localrepository(object):' | |||
|
1205 | 1225 | cls = repoview.newtype(self.unfiltered().__class__) |
|
1206 | 1226 | return cls(self, name, visibilityexceptions) |
|
1207 | 1227 | |
|
1208 |
@ |
|
|
1228 | @mixedrepostorecache(('bookmarks', ''), ('bookmarks.current', ''), | |
|
1229 | ('bookmarks', 'store')) | |
|
1209 | 1230 | def _bookmarks(self): |
|
1210 | 1231 | return bookmarks.bmstore(self) |
|
1211 | 1232 | |
@@ -1962,7 +1983,7 b' class localrepository(object):' | |||
|
1962 | 1983 | (self.vfs, 'journal.dirstate'), |
|
1963 | 1984 | (self.vfs, 'journal.branch'), |
|
1964 | 1985 | (self.vfs, 'journal.desc'), |
|
1965 |
(self |
|
|
1986 | (bookmarks.bookmarksvfs(self), 'journal.bookmarks'), | |
|
1966 | 1987 | (self.svfs, 'journal.phaseroots')) |
|
1967 | 1988 | |
|
1968 | 1989 | def undofiles(self): |
@@ -1977,8 +1998,9 b' class localrepository(object):' | |||
|
1977 | 1998 | encoding.fromlocal(self.dirstate.branch())) |
|
1978 | 1999 | self.vfs.write("journal.desc", |
|
1979 | 2000 | "%d\n%s\n" % (len(self), desc)) |
|
1980 | self.vfs.write("journal.bookmarks", | |
|
1981 | self.vfs.tryread("bookmarks")) | |
|
2001 | bookmarksvfs = bookmarks.bookmarksvfs(self) | |
|
2002 | bookmarksvfs.write("journal.bookmarks", | |
|
2003 | bookmarksvfs.tryread("bookmarks")) | |
|
1982 | 2004 | self.svfs.write("journal.phaseroots", |
|
1983 | 2005 | self.svfs.tryread("phaseroots")) |
|
1984 | 2006 | |
@@ -2048,8 +2070,9 b' class localrepository(object):' | |||
|
2048 | 2070 | vfsmap = {'plain': self.vfs, '': self.svfs} |
|
2049 | 2071 | transaction.rollback(self.svfs, vfsmap, 'undo', ui.warn, |
|
2050 | 2072 | checkambigfiles=_cachedfiles) |
|
2051 | if self.vfs.exists('undo.bookmarks'): | |
|
2052 | self.vfs.rename('undo.bookmarks', 'bookmarks', checkambig=True) | |
|
2073 | bookmarksvfs = bookmarks.bookmarksvfs(self) | |
|
2074 | if bookmarksvfs.exists('undo.bookmarks'): | |
|
2075 | bookmarksvfs.rename('undo.bookmarks', 'bookmarks', checkambig=True) | |
|
2053 | 2076 | if self.svfs.exists('undo.phaseroots'): |
|
2054 | 2077 | self.svfs.rename('undo.phaseroots', 'phaseroots', checkambig=True) |
|
2055 | 2078 | self.invalidate() |
@@ -3003,6 +3026,9 b' def newreporequirements(ui, createopts):' | |||
|
3003 | 3026 | if createopts.get('lfs'): |
|
3004 | 3027 | requirements.add('lfs') |
|
3005 | 3028 | |
|
3029 | if ui.configbool('format', 'bookmarks-in-store'): | |
|
3030 | requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT) | |
|
3031 | ||
|
3006 | 3032 | return requirements |
|
3007 | 3033 | |
|
3008 | 3034 | def filterknowncreateopts(ui, createopts): |
@@ -337,7 +337,7 b' def _calcmode(vfs):' | |||
|
337 | 337 | mode = None |
|
338 | 338 | return mode |
|
339 | 339 | |
|
340 | _data = ('narrowspec data meta 00manifest.d 00manifest.i' | |
|
340 | _data = ('bookmarks narrowspec data meta 00manifest.d 00manifest.i' | |
|
341 | 341 | ' 00changelog.d 00changelog.i phaseroots obsstore') |
|
342 | 342 | |
|
343 | 343 | def isrevlog(f, kind, st): |
@@ -612,7 +612,7 b' class fncachestore(basicstore):' | |||
|
612 | 612 | raise |
|
613 | 613 | |
|
614 | 614 | def copylist(self): |
|
615 | d = ('narrowspec data meta dh fncache phaseroots obsstore' | |
|
615 | d = ('bookmarks narrowspec data meta dh fncache phaseroots obsstore' | |
|
616 | 616 | ' 00manifest.d 00manifest.i 00changelog.d 00changelog.i') |
|
617 | 617 | return (['requires', '00changelog.i'] + |
|
618 | 618 | ['store/' + f for f in d.split()]) |
@@ -1513,6 +1513,8 b' Separate sections from subsections' | |||
|
1513 | 1513 | |
|
1514 | 1514 | "revlog-compression" |
|
1515 | 1515 | |
|
1516 | "bookmarks-in-store" | |
|
1517 | ||
|
1516 | 1518 | "profiling" |
|
1517 | 1519 | ----------- |
|
1518 | 1520 |
@@ -1,6 +1,13 b'' | |||
|
1 | #testcases vfs svfs | |
|
2 | ||
|
1 | 3 | $ echo "[extensions]" >> $HGRCPATH |
|
2 | 4 | $ echo "share = " >> $HGRCPATH |
|
3 | 5 | |
|
6 | #if svfs | |
|
7 | $ echo "[format]" >> $HGRCPATH | |
|
8 | $ echo "bookmarks-in-store = yes " >> $HGRCPATH | |
|
9 | #endif | |
|
10 | ||
|
4 | 11 | prepare repo1 |
|
5 | 12 | |
|
6 | 13 | $ hg init repo1 |
@@ -33,17 +40,21 b' test sharing bookmarks' | |||
|
33 | 40 | $ cd ../repo2 |
|
34 | 41 | $ hg book bm2 |
|
35 | 42 | $ hg bookmarks |
|
43 | bm1 2:c2e0ac586386 (svfs !) | |
|
36 | 44 | * bm2 2:c2e0ac586386 |
|
37 | 45 | $ cd ../repo3 |
|
38 | 46 | $ hg bookmarks |
|
39 | 47 | bm1 2:c2e0ac586386 |
|
48 | bm2 2:c2e0ac586386 (svfs !) | |
|
40 | 49 | $ hg book bm3 |
|
41 | 50 | $ hg bookmarks |
|
42 | 51 | bm1 2:c2e0ac586386 |
|
52 | bm2 2:c2e0ac586386 (svfs !) | |
|
43 | 53 | * bm3 2:c2e0ac586386 |
|
44 | 54 | $ cd ../repo1 |
|
45 | 55 | $ hg bookmarks |
|
46 | 56 | * bm1 2:c2e0ac586386 |
|
57 | bm2 2:c2e0ac586386 (svfs !) | |
|
47 | 58 | bm3 2:c2e0ac586386 |
|
48 | 59 | |
|
49 | 60 | check whether HG_PENDING makes pending changes only in relatd |
@@ -70,14 +81,18 b' Therefore, this test scenario ignores ch' | |||
|
70 | 81 | $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX |
|
71 | 82 | @repo1 |
|
72 | 83 | bm1 2:c2e0ac586386 |
|
84 | bm2 2:c2e0ac586386 (svfs !) | |
|
73 | 85 | bm3 2:c2e0ac586386 |
|
74 | 86 | * bmX 2:c2e0ac586386 |
|
75 | 87 | @repo2 |
|
88 | bm1 2:c2e0ac586386 (svfs !) | |
|
76 | 89 | * bm2 2:c2e0ac586386 |
|
90 | bm3 2:c2e0ac586386 (svfs !) | |
|
77 | 91 | @repo3 |
|
78 | 92 | bm1 2:c2e0ac586386 |
|
93 | bm2 2:c2e0ac586386 (svfs !) | |
|
79 | 94 | * bm3 2:c2e0ac586386 |
|
80 | bmX 2:c2e0ac586386 | |
|
95 | bmX 2:c2e0ac586386 (vfs !) | |
|
81 | 96 | transaction abort! |
|
82 | 97 | rollback completed |
|
83 | 98 | abort: pretxnclose hook exited with status 1 |
@@ -92,11 +107,15 b' src), because (1) HG_PENDING refers only' | |||
|
92 | 107 | $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX |
|
93 | 108 | @repo1 |
|
94 | 109 | * bm1 2:c2e0ac586386 |
|
110 | bm2 2:c2e0ac586386 (svfs !) | |
|
95 | 111 | bm3 2:c2e0ac586386 |
|
96 | 112 | @repo2 |
|
113 | bm1 2:c2e0ac586386 (svfs !) | |
|
97 | 114 | * bm2 2:c2e0ac586386 |
|
115 | bm3 2:c2e0ac586386 (svfs !) | |
|
98 | 116 | @repo3 |
|
99 | 117 | bm1 2:c2e0ac586386 |
|
118 | bm2 2:c2e0ac586386 (svfs !) | |
|
100 | 119 | bm3 2:c2e0ac586386 |
|
101 | 120 | * bmX 2:c2e0ac586386 |
|
102 | 121 | transaction abort! |
@@ -105,6 +124,11 b' src), because (1) HG_PENDING refers only' | |||
|
105 | 124 | [255] |
|
106 | 125 | $ hg book bm3 |
|
107 | 126 | |
|
127 | clean up bm2 since it's uninteresting (not shared in the vfs case and | |
|
128 | same as bm3 in the svfs case) | |
|
129 | $ cd ../repo2 | |
|
130 | $ hg book -d bm2 | |
|
131 | ||
|
108 | 132 | $ cd ../repo1 |
|
109 | 133 | |
|
110 | 134 | test that commits work |
General Comments 0
You need to be logged in to leave comments.
Login now