ยปCore Development>Code coverage>Tools/hg/hgtouch.py

Python code coverage for Tools/hg/hgtouch.py

#countcontent
1n/a"""Bring time stamps of generated checked-in files into the right order
2n/a
3n/aA versioned configuration file .hgtouch specifies generated files, in the
4n/asyntax of make rules.
5n/a
6n/a output: input1 input2
7n/a
8n/aIn addition to the dependency syntax, #-comments are supported.
9n/a"""
10n/aimport errno
11n/aimport os
12n/aimport time
13n/a
14n/adef parse_config(repo):
15n/a try:
16n/a fp = repo.wfile(".hgtouch")
17n/a except IOError, e:
18n/a if e.errno != errno.ENOENT:
19n/a raise
20n/a return {}
21n/a result = {}
22n/a with fp:
23n/a for line in fp:
24n/a # strip comments
25n/a line = line.split('#')[0].strip()
26n/a if ':' not in line:
27n/a continue
28n/a outputs, inputs = line.split(':', 1)
29n/a outputs = outputs.split()
30n/a inputs = inputs.split()
31n/a for o in outputs:
32n/a try:
33n/a result[o].extend(inputs)
34n/a except KeyError:
35n/a result[o] = inputs
36n/a return result
37n/a
38n/adef check_rule(ui, repo, modified, basedir, output, inputs):
39n/a """Verify that the output is newer than any of the inputs.
40n/a Return (status, stamp), where status is True if the update succeeded,
41n/a and stamp is the newest time stamp assigned to any file (might be in
42n/a the future).
43n/a
44n/a If basedir is nonempty, it gives a directory in which the tree is to
45n/a be checked.
46n/a """
47n/a f_output = repo.wjoin(os.path.join(basedir, output))
48n/a try:
49n/a o_time = os.stat(f_output).st_mtime
50n/a except OSError:
51n/a ui.warn("Generated file %s does not exist\n" % output)
52n/a return False, 0
53n/a youngest = 0 # youngest dependency
54n/a backdate = None
55n/a backdate_source = None
56n/a for i in inputs:
57n/a f_i = repo.wjoin(os.path.join(basedir, i))
58n/a try:
59n/a i_time = os.stat(f_i).st_mtime
60n/a except OSError:
61n/a ui.warn(".hgtouch input file %s does not exist\n" % i)
62n/a return False, 0
63n/a if i in modified:
64n/a # input is modified. Need to backdate at least to i_time
65n/a if backdate is None or backdate > i_time:
66n/a backdate = i_time
67n/a backdate_source = i
68n/a continue
69n/a youngest = max(i_time, youngest)
70n/a if backdate is not None:
71n/a ui.warn("Input %s for file %s locally modified\n" % (backdate_source, output))
72n/a # set to 1s before oldest modified input
73n/a backdate -= 1
74n/a os.utime(f_output, (backdate, backdate))
75n/a return False, 0
76n/a if youngest >= o_time:
77n/a ui.note("Touching %s\n" % output)
78n/a youngest += 1
79n/a os.utime(f_output, (youngest, youngest))
80n/a return True, youngest
81n/a else:
82n/a # Nothing to update
83n/a return True, 0
84n/a
85n/adef do_touch(ui, repo, basedir):
86n/a if basedir:
87n/a if not os.path.isdir(repo.wjoin(basedir)):
88n/a ui.warn("Abort: basedir %r does not exist\n" % basedir)
89n/a return
90n/a modified = []
91n/a else:
92n/a modified = repo.status()[0]
93n/a dependencies = parse_config(repo)
94n/a success = True
95n/a tstamp = 0 # newest time stamp assigned
96n/a # try processing all rules in topological order
97n/a hold_back = {}
98n/a while dependencies:
99n/a output, inputs = dependencies.popitem()
100n/a # check whether any of the inputs is generated
101n/a for i in inputs:
102n/a if i in dependencies:
103n/a hold_back[output] = inputs
104n/a continue
105n/a _success, _tstamp = check_rule(ui, repo, modified, basedir, output, inputs)
106n/a success = success and _success
107n/a tstamp = max(tstamp, _tstamp)
108n/a # put back held back rules
109n/a dependencies.update(hold_back)
110n/a hold_back = {}
111n/a now = time.time()
112n/a if tstamp > now:
113n/a # wait until real time has passed the newest time stamp, to
114n/a # avoid having files dated in the future
115n/a time.sleep(tstamp-now)
116n/a if hold_back:
117n/a ui.warn("Cyclic dependency involving %s\n" % (' '.join(hold_back.keys())))
118n/a return False
119n/a return success
120n/a
121n/adef touch(ui, repo, basedir):
122n/a "touch generated files that are older than their sources after an update."
123n/a do_touch(ui, repo, basedir)
124n/a
125n/acmdtable = {
126n/a "touch": (touch,
127n/a [('b', 'basedir', '', 'base dir of the tree to apply touching')],
128n/a "hg touch [-b BASEDIR]")
129n/a}