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

40 statements  

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# 

20 

21"""Utilities for reading and generating reflogs.""" 

22 

23import collections 

24 

25from .objects import ZERO_SHA, format_timezone, parse_timezone 

26 

27Entry = collections.namedtuple( 

28 "Entry", 

29 ["old_sha", "new_sha", "committer", "timestamp", "timezone", "message"], 

30) 

31 

32 

33def format_reflog_line(old_sha, new_sha, committer, timestamp, timezone, message): 

34 """Generate a single reflog line. 

35 

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 ) 

59 

60 

61def parse_reflog_line(line): 

62 """Parse a reflog line. 

63 

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 ) 

80 

81 

82def read_reflog(f): 

83 """Read reflog. 

84 

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) 

91 

92 

93def drop_reflog_entry(f, index, rewrite=False): 

94 """Drop the specified reflog entry. 

95 

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) 

104 

105 log = [] 

106 offset = f.tell() 

107 for line in f: 

108 log.append((offset, parse_reflog_line(line))) 

109 offset = f.tell() 

110 

111 inverse_index = len(log) - index - 1 

112 write_offset = log[inverse_index][0] 

113 f.seek(write_offset) 

114 

115 if index == 0: 

116 f.truncate() 

117 return 

118 

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 ) 

137 

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()