annotate mercurial/state.py @ 38136:a2f83661f721

state: import the file to write state files from evolve extension The current way of writing state files is very obscure with each state file having it's own format to store state files. There is no centralized way to write state files in a good format. Moreover the current state files are not extensible, you cannot add more data to store in state files in reliable ways. To solve the problem, I wrote my own serialization and deserialization format, looked into existing formats like Protobuf, MessagePack, JSON but CBOR looks very promising and is suggested by people in the community. The current interface to store state files is to directly write data in files when things abort. Using the class imported by this commit, we can create objects which has a dict like interface and can store data on the object and store it on the file when things abort. The evolve extension is using the state file for `evolve`, `grab` commands and using it for resolution of orphaness, phase-divergence and content-divergence. The file is moved from changeset e4ac2e2c2086f977afa35e23a62f849e9305a225 of the evolve extension which is also tagged as 7.3.0. The following changes are made to the file while moving to core: * import util from current directory as this file in mercurial/ now * make cmdstate class extend object * removed mutable default value for opts in cmdstate.__init__ * some doc changes to replace out of core things with in-core ones evolve extension can be found at https://bitbucket.org/marmoute/mutable-history Differential Revision: https://phab.mercurial-scm.org/D2591
author Pulkit Goyal <7895pulkit@gmail.com>
date Wed, 21 Feb 2018 17:20:22 +0530
parents
children 36a5a1239a15
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
38136
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
1 # state.py - writing and reading state files in Mercurial
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
2 #
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
3 # Copyright 2018 Pulkit Goyal <pulkitmgoyal@gmail.com>
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
4 #
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
7
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
8 """
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
9 This file contains class to wrap the state for commands and other
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
10 related logic.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
11
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
12 All the data related to the command state is stored as dictionary in the object.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
13 The class has methods using which the data can be stored to disk in a file under
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
14 .hg/ directory.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
15
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
16 We store the data on disk in cbor, for which we use the third party cbor library
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
17 to serialize and deserialize data.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
18 """
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
19
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
20 from __future__ import absolute_import
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
21
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
22 from .thirdparty import cbor
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
23
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
24 from . import (
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
25 util,
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
26 )
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
27
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
28 class cmdstate(object):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
29 """a wrapper class to store the state of commands like `rebase`, `graft`,
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
30 `histedit`, `shelve` etc. Extensions can also use this to write state files.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
31
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
32 All the data for the state is stored in the form of key-value pairs in a
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
33 dictionary.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
34
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
35 The class object can write all the data to a file in .hg/ directory and
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
36 can populate the object data reading that file.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
37
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
38 Uses cbor to serialize and deserialize data while writing and reading from
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
39 disk.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
40 """
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
41
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
42 def __init__(self, repo, fname, opts=None):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
43 """ repo is the repo object
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
44 fname is the file name in which data should be stored in .hg directory
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
45 opts is a dictionary of data of the statefile
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
46 """
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
47 self._repo = repo
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
48 self.fname = fname
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
49 if not opts:
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
50 self.opts = {}
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
51 else:
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
52 self.opts = opts
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
53
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
54 def __nonzero__(self):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
55 return self.exists()
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
56
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
57 def __getitem__(self, key):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
58 return self.opts[key]
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
59
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
60 def __setitem__(self, key, value):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
61 updates = {key: value}
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
62 self.opts.update(updates)
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
63
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
64 def load(self):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
65 """load the existing state file into the class object"""
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
66 op = self._read()
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
67 self.opts.update(op)
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
68
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
69 def addopts(self, opts):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
70 """add more key-value pairs to the data stored by the object"""
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
71 self.opts.update(opts)
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
72
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
73 def save(self):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
74 """write all the state data stored to .hg/<filename> file
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
75
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
76 we use third-party library cbor to serialize data to write in the file.
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
77 """
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
78 with self._repo.vfs(self.fname, 'wb', atomictemp=True) as fp:
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
79 cbor.dump(self.opts, fp)
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
80
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
81 def _read(self):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
82 """reads the state file and returns a dictionary which contain
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
83 data in the same format as it was before storing"""
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
84 with self._repo.vfs(self.fname, 'rb') as fp:
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
85 return cbor.load(fp)
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
86
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
87 def delete(self):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
88 """drop the state file if exists"""
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
89 util.unlinkpath(self._repo.vfs.join(self.fname), ignoremissing=True)
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
90
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
91 def exists(self):
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
92 """check whether the state file exists or not"""
a2f83661f721 state: import the file to write state files from evolve extension
Pulkit Goyal <7895pulkit@gmail.com>
parents:
diff changeset
93 return self._repo.vfs.exists(self.fname)