Mercurial > hg
annotate hgext/journal.py @ 29443:cf092a3d202a
journal: new experimental extension
Records bookmark locations and shows you where bookmarks were located in the
past.
This is the first in a planned series of locations to be recorded; a future
patch will add working copy (dirstate) tracking, and remote bookmarks will be
supported as well, so the journal storage format should be fairly generic to
support those use-cases.
author | Martijn Pieters <mjpieters@fb.com> |
---|---|
date | Fri, 24 Jun 2016 16:12:05 +0100 |
parents | |
children | 8361131b4768 |
rev | line source |
---|---|
29443
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
1 # journal.py |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
2 # |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
3 # Copyright 2014-2016 Facebook, Inc. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
4 # |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
6 # GNU General Public License version 2 or any later version. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
7 """Track previous positions of bookmarks (EXPERIMENTAL) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
8 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
9 This extension adds a new command: `hg journal`, which shows you where |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
10 bookmarks were previously located. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
11 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
12 """ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
13 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
14 from __future__ import absolute_import |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
15 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
16 import collections |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
17 import os |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
18 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
19 from mercurial.i18n import _ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
20 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
21 from mercurial import ( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
22 bookmarks, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
23 cmdutil, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
24 commands, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
25 dispatch, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
26 error, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
27 extensions, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
28 node, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
29 util, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
30 ) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
31 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
32 cmdtable = {} |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
33 command = cmdutil.command(cmdtable) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
34 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
35 # Note for extension authors: ONLY specify testedwith = 'internal' for |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
36 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
37 # be specifying the version(s) of Mercurial they are tested with, or |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
38 # leave the attribute unspecified. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
39 testedwith = 'internal' |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
40 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
41 # storage format version; increment when the format changes |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
42 storageversion = 0 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
43 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
44 # namespaces |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
45 bookmarktype = 'bookmark' |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
46 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
47 # Journal recording, register hooks and storage object |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
48 def extsetup(ui): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
49 extensions.wrapfunction(dispatch, 'runcommand', runcommand) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
50 extensions.wrapfunction(bookmarks.bmstore, '_write', recordbookmarks) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
51 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
52 def reposetup(ui, repo): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
53 if repo.local(): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
54 repo.journal = journalstorage(repo) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
55 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
56 def runcommand(orig, lui, repo, cmd, fullargs, *args): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
57 """Track the command line options for recording in the journal""" |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
58 journalstorage.recordcommand(*fullargs) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
59 return orig(lui, repo, cmd, fullargs, *args) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
60 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
61 def recordbookmarks(orig, store, fp): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
62 """Records all bookmark changes in the journal.""" |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
63 repo = store._repo |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
64 if util.safehasattr(repo, 'journal'): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
65 oldmarks = bookmarks.bmstore(repo) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
66 for mark, value in store.iteritems(): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
67 oldvalue = oldmarks.get(mark, node.nullid) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
68 if value != oldvalue: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
69 repo.journal.record(bookmarktype, mark, oldvalue, value) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
70 return orig(store, fp) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
71 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
72 class journalentry(collections.namedtuple( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
73 'journalentry', |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
74 'timestamp user command namespace name oldhashes newhashes')): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
75 """Individual journal entry |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
76 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
77 * timestamp: a mercurial (time, timezone) tuple |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
78 * user: the username that ran the command |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
79 * namespace: the entry namespace, an opaque string |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
80 * name: the name of the changed item, opaque string with meaning in the |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
81 namespace |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
82 * command: the hg command that triggered this record |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
83 * oldhashes: a tuple of one or more binary hashes for the old location |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
84 * newhashes: a tuple of one or more binary hashes for the new location |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
85 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
86 Handles serialisation from and to the storage format. Fields are |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
87 separated by newlines, hashes are written out in hex separated by commas, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
88 timestamp and timezone are separated by a space. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
89 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
90 """ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
91 @classmethod |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
92 def fromstorage(cls, line): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
93 (time, user, command, namespace, name, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
94 oldhashes, newhashes) = line.split('\n') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
95 timestamp, tz = time.split() |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
96 timestamp, tz = float(timestamp), int(tz) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
97 oldhashes = tuple(node.bin(hash) for hash in oldhashes.split(',')) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
98 newhashes = tuple(node.bin(hash) for hash in newhashes.split(',')) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
99 return cls( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
100 (timestamp, tz), user, command, namespace, name, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
101 oldhashes, newhashes) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
102 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
103 def __str__(self): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
104 """String representation for storage""" |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
105 time = ' '.join(map(str, self.timestamp)) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
106 oldhashes = ','.join([node.hex(hash) for hash in self.oldhashes]) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
107 newhashes = ','.join([node.hex(hash) for hash in self.newhashes]) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
108 return '\n'.join(( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
109 time, self.user, self.command, self.namespace, self.name, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
110 oldhashes, newhashes)) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
111 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
112 class journalstorage(object): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
113 """Storage for journal entries |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
114 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
115 Entries are stored with NUL bytes as separators. See the journalentry |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
116 class for the per-entry structure. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
117 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
118 The file format starts with an integer version, delimited by a NUL. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
119 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
120 """ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
121 _currentcommand = () |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
122 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
123 def __init__(self, repo): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
124 self.repo = repo |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
125 self.user = util.getuser() |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
126 self.vfs = repo.vfs |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
127 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
128 # track the current command for recording in journal entries |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
129 @property |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
130 def command(self): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
131 commandstr = ' '.join( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
132 map(util.shellquote, journalstorage._currentcommand)) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
133 if '\n' in commandstr: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
134 # truncate multi-line commands |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
135 commandstr = commandstr.partition('\n')[0] + ' ...' |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
136 return commandstr |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
137 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
138 @classmethod |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
139 def recordcommand(cls, *fullargs): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
140 """Set the current hg arguments, stored with recorded entries""" |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
141 # Set the current command on the class because we may have started |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
142 # with a non-local repo (cloning for example). |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
143 cls._currentcommand = fullargs |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
144 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
145 def record(self, namespace, name, oldhashes, newhashes): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
146 """Record a new journal entry |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
147 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
148 * namespace: an opaque string; this can be used to filter on the type |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
149 of recorded entries. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
150 * name: the name defining this entry; for bookmarks, this is the |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
151 bookmark name. Can be filtered on when retrieving entries. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
152 * oldhashes and newhashes: each a single binary hash, or a list of |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
153 binary hashes. These represent the old and new position of the named |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
154 item. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
155 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
156 """ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
157 if not isinstance(oldhashes, list): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
158 oldhashes = [oldhashes] |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
159 if not isinstance(newhashes, list): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
160 newhashes = [newhashes] |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
161 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
162 entry = journalentry( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
163 util.makedate(), self.user, self.command, namespace, name, |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
164 oldhashes, newhashes) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
165 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
166 with self.repo.wlock(): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
167 version = None |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
168 # open file in amend mode to ensure it is created if missing |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
169 with self.vfs('journal', mode='a+b', atomictemp=True) as f: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
170 f.seek(0, os.SEEK_SET) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
171 # Read just enough bytes to get a version number (up to 2 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
172 # digits plus separator) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
173 version = f.read(3).partition('\0')[0] |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
174 if version and version != str(storageversion): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
175 # different version of the storage. Exit early (and not |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
176 # write anything) if this is not a version we can handle or |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
177 # the file is corrupt. In future, perhaps rotate the file |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
178 # instead? |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
179 self.repo.ui.warn( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
180 _("unsupported journal file version '%s'\n") % version) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
181 return |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
182 if not version: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
183 # empty file, write version first |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
184 f.write(str(storageversion) + '\0') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
185 f.seek(0, os.SEEK_END) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
186 f.write(str(entry) + '\0') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
187 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
188 def filtered(self, namespace=None, name=None): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
189 """Yield all journal entries with the given namespace or name |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
190 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
191 Both the namespace and the name are optional; if neither is given all |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
192 entries in the journal are produced. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
193 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
194 """ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
195 for entry in self: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
196 if namespace is not None and entry.namespace != namespace: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
197 continue |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
198 if name is not None and entry.name != name: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
199 continue |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
200 yield entry |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
201 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
202 def __iter__(self): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
203 """Iterate over the storage |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
204 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
205 Yields journalentry instances for each contained journal record. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
206 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
207 """ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
208 if not self.vfs.exists('journal'): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
209 return |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
210 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
211 with self.vfs('journal') as f: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
212 raw = f.read() |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
213 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
214 lines = raw.split('\0') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
215 version = lines and lines[0] |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
216 if version != str(storageversion): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
217 version = version or _('not available') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
218 raise error.Abort(_("unknown journal file version '%s'") % version) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
219 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
220 # Skip the first line, it's a version number. Reverse the rest. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
221 lines = reversed(lines[1:]) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
222 for line in lines: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
223 if not line: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
224 continue |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
225 yield journalentry.fromstorage(line) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
226 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
227 # journal reading |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
228 # log options that don't make sense for journal |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
229 _ignoreopts = ('no-merges', 'graph') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
230 @command( |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
231 'journal', [ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
232 ('c', 'commits', None, 'show commit metadata'), |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
233 ] + [opt for opt in commands.logopts if opt[1] not in _ignoreopts], |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
234 '[OPTION]... [BOOKMARKNAME]') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
235 def journal(ui, repo, *args, **opts): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
236 """show the previous position of bookmarks |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
237 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
238 The journal is used to see the previous commits of bookmarks. By default |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
239 the previous locations for all bookmarks are shown. Passing a bookmark |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
240 name will show all the previous positions of that bookmark. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
241 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
242 By default hg journal only shows the commit hash and the command that was |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
243 running at that time. -v/--verbose will show the prior hash, the user, and |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
244 the time at which it happened. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
245 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
246 Use -c/--commits to output log information on each commit hash; at this |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
247 point you can use the usual `--patch`, `--git`, `--stat` and `--template` |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
248 switches to alter the log output for these. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
249 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
250 `hg journal -T json` can be used to produce machine readable output. |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
251 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
252 """ |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
253 bookmarkname = None |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
254 if args: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
255 bookmarkname = args[0] |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
256 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
257 fm = ui.formatter('journal', opts) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
258 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
259 if opts.get("template") != "json": |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
260 if bookmarkname is None: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
261 name = _('all bookmarks') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
262 else: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
263 name = "'%s'" % bookmarkname |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
264 ui.status(_("previous locations of %s:\n") % name) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
265 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
266 limit = cmdutil.loglimit(opts) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
267 entry = None |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
268 for count, entry in enumerate(repo.journal.filtered(name=bookmarkname)): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
269 if count == limit: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
270 break |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
271 newhashesstr = ','.join([node.short(hash) for hash in entry.newhashes]) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
272 oldhashesstr = ','.join([node.short(hash) for hash in entry.oldhashes]) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
273 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
274 fm.startitem() |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
275 fm.condwrite(ui.verbose, 'oldhashes', '%s -> ', oldhashesstr) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
276 fm.write('newhashes', '%s', newhashesstr) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
277 fm.condwrite(ui.verbose, 'user', ' %s', entry.user.ljust(8)) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
278 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
279 timestring = util.datestr(entry.timestamp, '%Y-%m-%d %H:%M %1%2') |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
280 fm.condwrite(ui.verbose, 'date', ' %s', timestring) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
281 fm.write('command', ' %s\n', entry.command) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
282 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
283 if opts.get("commits"): |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
284 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=False) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
285 for hash in entry.newhashes: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
286 try: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
287 ctx = repo[hash] |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
288 displayer.show(ctx) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
289 except error.RepoLookupError as e: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
290 fm.write('repolookuperror', "%s\n\n", str(e)) |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
291 displayer.close() |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
292 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
293 fm.end() |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
294 |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
295 if entry is None: |
cf092a3d202a
journal: new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff
changeset
|
296 ui.status(_("no recorded locations\n")) |