Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/dulwich/reflog.py: 28%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# reflog.py -- Parsing and writing reflog files
2# Copyright (C) 2015 Jelmer Vernooij and others.
3#
4# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
5# General Public License as public by the Free Software Foundation; version 2.0
6# or (at your option) any later version. You can redistribute it and/or
7# modify it under the terms of either of these two licenses.
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15# You should have received a copy of the licenses; if not, see
16# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
17# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
18# License, Version 2.0.
19#
21"""Utilities for reading and generating reflogs."""
23import collections
25from .objects import ZERO_SHA, format_timezone, parse_timezone
27Entry = collections.namedtuple(
28 "Entry",
29 ["old_sha", "new_sha", "committer", "timestamp", "timezone", "message"],
30)
33def format_reflog_line(old_sha, new_sha, committer, timestamp, timezone, message):
34 """Generate a single reflog line.
36 Args:
37 old_sha: Old Commit SHA
38 new_sha: New Commit SHA
39 committer: Committer name and e-mail
40 timestamp: Timestamp
41 timezone: Timezone
42 message: Message
43 """
44 if old_sha is None:
45 old_sha = ZERO_SHA
46 return (
47 old_sha
48 + b" "
49 + new_sha
50 + b" "
51 + committer
52 + b" "
53 + str(int(timestamp)).encode("ascii")
54 + b" "
55 + format_timezone(timezone)
56 + b"\t"
57 + message
58 )
61def parse_reflog_line(line):
62 """Parse a reflog line.
64 Args:
65 line: Line to parse
66 Returns: Tuple of (old_sha, new_sha, committer, timestamp, timezone,
67 message)
68 """
69 (begin, message) = line.split(b"\t", 1)
70 (old_sha, new_sha, rest) = begin.split(b" ", 2)
71 (committer, timestamp_str, timezone_str) = rest.rsplit(b" ", 2)
72 return Entry(
73 old_sha,
74 new_sha,
75 committer,
76 int(timestamp_str),
77 parse_timezone(timezone_str)[0],
78 message,
79 )
82def read_reflog(f):
83 """Read reflog.
85 Args:
86 f: File-like object
87 Returns: Iterator over Entry objects
88 """
89 for line in f:
90 yield parse_reflog_line(line)
93def drop_reflog_entry(f, index, rewrite=False):
94 """Drop the specified reflog entry.
96 Args:
97 f: File-like object
98 index: Reflog entry index (in Git reflog reverse 0-indexed order)
99 rewrite: If a reflog entry's predecessor is removed, set its
100 old SHA to the new SHA of the entry that now precedes it
101 """
102 if index < 0:
103 raise ValueError("Invalid reflog index %d" % index)
105 log = []
106 offset = f.tell()
107 for line in f:
108 log.append((offset, parse_reflog_line(line)))
109 offset = f.tell()
111 inverse_index = len(log) - index - 1
112 write_offset = log[inverse_index][0]
113 f.seek(write_offset)
115 if index == 0:
116 f.truncate()
117 return
119 del log[inverse_index]
120 if rewrite and index > 0 and log:
121 if inverse_index == 0:
122 previous_new = ZERO_SHA
123 else:
124 previous_new = log[inverse_index - 1][1].new_sha
125 offset, entry = log[inverse_index]
126 log[inverse_index] = (
127 offset,
128 Entry(
129 previous_new,
130 entry.new_sha,
131 entry.committer,
132 entry.timestamp,
133 entry.timezone,
134 entry.message,
135 ),
136 )
138 for _, entry in log[inverse_index:]:
139 f.write(
140 format_reflog_line(
141 entry.old_sha,
142 entry.new_sha,
143 entry.committer,
144 entry.timestamp,
145 entry.timezone,
146 entry.message,
147 )
148 )
149 f.truncate()