| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5bd7d44 commit a21a9f6
11 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -37,7 +37,8 @@ def _init_externals(): | |||
| 37 | 37 | from git.util import ( | |
| 38 | 38 | LockFile, | |
| 39 | 39 | BlockingLockFile, | |
| 40 | - Stats | ||
| 40 | + Stats, | ||
| 41 | + Actor | ||
| 41 | 42 | ) | |
| 42 | 43 | ||
| 43 | 44 | #} END imports | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,7 +15,6 @@ | |||
| 15 | 15 | from blob import * | |
| 16 | 16 | from commit import * | |
| 17 | 17 | from tree import * | |
| 18 | - from util import Actor | ||
| 19 | 18 | ||
| 20 | 19 | __all__ = [ name for name, obj in locals().items() | |
| 21 | 20 | if not (name.startswith('_') or inspect.ismodule(obj)) ] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,7 +4,8 @@ | |||
| 4 | 4 | # This module is part of GitPython and is released under | |
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | 6 | ||
| 7 | - from git.util import ( | ||
| 7 | + from git.util import ( | ||
| 8 | + Actor, | ||
| 8 | 9 | Iterable, | |
| 9 | 10 | Stats, | |
| 10 | 11 | ) | |
@@ -20,9 +21,7 @@ | |||
| 20 | 21 | from util import ( | |
| 21 | 22 | Traversable, | |
| 22 | 23 | Serializable, | |
| 23 | - get_user_id, | ||
| 24 | 24 | parse_date, | |
| 25 | - Actor, | ||
| 26 | 25 | altz_to_utctz_str, | |
| 27 | 26 | parse_actor_and_date | |
| 28 | 27 | ) | |
@@ -43,17 +42,10 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable): | |||
| 43 | 42 | ||
| 44 | 43 | # ENVIRONMENT VARIABLES | |
| 45 | 44 | # read when creating new commits | |
| 46 | - env_author_name = "GIT_AUTHOR_NAME" | ||
| 47 | - env_author_email = "GIT_AUTHOR_EMAIL" | ||
| 48 | 45 | env_author_date = "GIT_AUTHOR_DATE" | |
| 49 | - env_committer_name = "GIT_COMMITTER_NAME" | ||
| 50 | - env_committer_email = "GIT_COMMITTER_EMAIL" | ||
| 51 | 46 | env_committer_date = "GIT_COMMITTER_DATE" | |
| 52 | - env_email = "EMAIL" | ||
| 53 | 47 | ||
| 54 | 48 | # CONFIGURATION KEYS | |
| 55 | - conf_name = 'name' | ||
| 56 | - conf_email = 'email' | ||
| 57 | 49 | conf_encoding = 'i18n.commitencoding' | |
| 58 | 50 | ||
| 59 | 51 | # INVARIANTS | |
@@ -306,17 +298,9 @@ def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False): | |||
| 306 | 298 | # COMMITER AND AUTHOR INFO | |
| 307 | 299 | cr = repo.config_reader() | |
| 308 | 300 | env = os.environ | |
| 309 | - default_email = get_user_id() | ||
| 310 | - default_name = default_email.split('@')[0] | ||
| 311 | 301 | ||
| 312 | - conf_name = cr.get_value('user', cls.conf_name, default_name) | ||
| 313 | - conf_email = cr.get_value('user', cls.conf_email, default_email) | ||
| 314 | - | ||
| 315 | - author_name = env.get(cls.env_author_name, conf_name) | ||
| 316 | - author_email = env.get(cls.env_author_email, conf_email) | ||
| 317 | - | ||
| 318 | - committer_name = env.get(cls.env_committer_name, conf_name) | ||
| 319 | - committer_email = env.get(cls.env_committer_email, conf_email) | ||
| 302 | + committer = Actor.committer(cr) | ||
| 303 | + author = Actor.author(cr) | ||
| 320 | 304 | ||
| 321 | 305 | # PARSE THE DATES | |
| 322 | 306 | unix_time = int(time()) | |
@@ -340,9 +324,6 @@ def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False): | |||
| 340 | 324 | enc_section, enc_option = cls.conf_encoding.split('.') | |
| 341 | 325 | conf_encoding = cr.get_value(enc_section, enc_option, cls.default_encoding) | |
| 342 | 326 | ||
| 343 | - author = Actor(author_name, author_email) | ||
| 344 | - committer = Actor(committer_name, committer_email) | ||
| 345 | - | ||
| 346 | 327 | ||
| 347 | 328 | # if the tree is no object, make sure we create one - otherwise | |
| 348 | 329 | # the created commit object is invalid | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,19 +4,21 @@ | |||
| 4 | 4 | # This module is part of GitPython and is released under | |
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | 6 | """Module for general utility functions""" | |
| 7 | - from git.util import IterableList | ||
| 7 | + from git.util import ( | ||
| 8 | + IterableList, | ||
| 9 | + Actor | ||
| 10 | + ) | ||
| 8 | 11 | ||
| 9 | 12 | import re | |
| 10 | 13 | from collections import deque as Deque | |
| 11 | - import platform | ||
| 12 | 14 | ||
| 13 | 15 | from string import digits | |
| 14 | 16 | import time | |
| 15 | 17 | import os | |
| 16 | 18 | ||
| 17 | - __all__ = ('get_object_type_by_name', 'get_user_id', 'parse_date', 'parse_actor_and_date', | ||
| 19 | + __all__ = ('get_object_type_by_name', 'parse_date', 'parse_actor_and_date', | ||
| 18 | 20 | 'ProcessStreamAdapter', 'Traversable', 'altz_to_utctz_str', 'utctz_to_altz', | |
| 19 | - 'verify_utctz') | ||
| 21 | + 'verify_utctz', 'Actor') | ||
| 20 | 22 | ||
| 21 | 23 | #{ Functions | |
| 22 | 24 | ||
@@ -57,18 +59,6 @@ def get_object_type_by_name(object_type_name): | |||
| 57 | 59 | else: | |
| 58 | 60 | raise ValueError("Cannot handle unknown object type: %s" % object_type_name) | |
| 59 | 61 | ||
| 60 | - | ||
| 61 | - def get_user_id(): | ||
| 62 | - """:return: string identifying the currently active system user as name@node | ||
| 63 | - :note: user can be set with the 'USER' environment variable, usually set on windows""" | ||
| 64 | - ukn = 'UNKNOWN' | ||
| 65 | - username = os.environ.get('USER', os.environ.get('USERNAME', ukn)) | ||
| 66 | - if username == ukn and hasattr(os, 'getlogin'): | ||
| 67 | - username = os.getlogin() | ||
| 68 | - # END get username from login | ||
| 69 | - return "%s@%s" % (username, platform.node()) | ||
| 70 | - | ||
| 71 | - | ||
| 72 | 62 | def utctz_to_altz(utctz): | |
| 73 | 63 | """we convert utctz to the timezone in seconds, it is the format time.altzone | |
| 74 | 64 | returns. Git stores it as UTC timezone which has the opposite sign as well, | |
@@ -193,58 +183,6 @@ def parse_actor_and_date(line): | |||
| 193 | 183 | ||
| 194 | 184 | ||
| 195 | 185 | #{ Classes | |
| 196 | - | ||
| 197 | - class Actor(object): | ||
| 198 | - """Actors hold information about a person acting on the repository. They | ||
| 199 | - can be committers and authors or anything with a name and an email as | ||
| 200 | - mentioned in the git log entries.""" | ||
| 201 | - # precompiled regex | ||
| 202 | - name_only_regex = re.compile( r'<(.+)>' ) | ||
| 203 | - name_email_regex = re.compile( r'(.*) <(.+?)>' ) | ||
| 204 | - | ||
| 205 | - __slots__ = ('name', 'email') | ||
| 206 | - | ||
| 207 | - def __init__(self, name, email): | ||
| 208 | - self.name = name | ||
| 209 | - self.email = email | ||
| 210 | - | ||
| 211 | - def __eq__(self, other): | ||
| 212 | - return self.name == other.name and self.email == other.email | ||
| 213 | - | ||
| 214 | - def __ne__(self, other): | ||
| 215 | - return not (self == other) | ||
| 216 | - | ||
| 217 | - def __hash__(self): | ||
| 218 | - return hash((self.name, self.email)) | ||
| 219 | - | ||
| 220 | - def __str__(self): | ||
| 221 | - return self.name | ||
| 222 | - | ||
| 223 | - def __repr__(self): | ||
| 224 | - return '<git.Actor "%s <%s>">' % (self.name, self.email) | ||
| 225 | - | ||
| 226 | - @classmethod | ||
| 227 | - def _from_string(cls, string): | ||
| 228 | - """Create an Actor from a string. | ||
| 229 | - :param string: is the string, which is expected to be in regular git format | ||
| 230 | - | ||
| 231 | - John Doe <jdoe@example.com> | ||
| 232 | - | ||
| 233 | - :return: Actor """ | ||
| 234 | - m = cls.name_email_regex.search(string) | ||
| 235 | - if m: | ||
| 236 | - name, email = m.groups() | ||
| 237 | - return Actor(name, email) | ||
| 238 | - else: | ||
| 239 | - m = cls.name_only_regex.search(string) | ||
| 240 | - if m: | ||
| 241 | - return Actor(m.group(1), None) | ||
| 242 | - else: | ||
| 243 | - # assume best and use the whole string as name | ||
| 244 | - return Actor(string, None) | ||
| 245 | - # END special case name | ||
| 246 | - # END handle name/email matching | ||
| 247 | - | ||
| 248 | 186 | ||
| 249 | 187 | class ProcessStreamAdapter(object): | |
| 250 | 188 | """Class wireing all calls to the contained Process instance. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,17 +1,22 @@ | |||
| 1 | - from git.util import join_path | ||
| 1 | + from git.util import ( | ||
| 2 | + join_path, | ||
| 3 | + Actor, | ||
| 4 | + ) | ||
| 5 | + | ||
| 2 | 6 | from gitdb.util import ( | |
| 7 | + bin_to_hex, | ||
| 3 | 8 | join, | |
| 4 | 9 | file_contents_ro_filepath | |
| 5 | 10 | ) | |
| 6 | 11 | ||
| 7 | 12 | from git.objects.util import ( | |
| 8 | - Actor, | ||
| 9 | 13 | parse_date, | |
| 10 | 14 | Serializable, | |
| 11 | 15 | utctz_to_altz, | |
| 12 | 16 | altz_to_utctz_str, | |
| 13 | 17 | ) | |
| 14 | 18 | ||
| 19 | + import time | ||
| 15 | 20 | import os | |
| 16 | 21 | import re | |
| 17 | 22 | ||
@@ -104,7 +109,28 @@ class RefLog(list, Serializable): | |||
| 104 | 109 | Reflog entries are orded, the first added entry is first in the list, the last | |
| 105 | 110 | entry, i.e. the last change of the head or reference, is last in the list.""" | |
| 106 | 111 | ||
| 107 | - __slots__ = tuple() | ||
| 112 | + __slots__ = ('_path', ) | ||
| 113 | + | ||
| 114 | + def __new__(cls, filepath=None): | ||
| 115 | + inst = super(RefLog, cls).__new__(cls) | ||
| 116 | + return inst | ||
| 117 | + | ||
| 118 | + def __init__(self, filepath=None): | ||
| 119 | + """Initialize this instance with an optional filepath, from which we will | ||
| 120 | + initialize our data. The path is also used to write changes back using | ||
| 121 | + the write() method""" | ||
| 122 | + self._path = filepath | ||
| 123 | + if filepath is not None: | ||
| 124 | + self._read_from_file() | ||
| 125 | + # END handle filepath | ||
| 126 | + | ||
| 127 | + def _read_from_file(self): | ||
| 128 | + fmap = file_contents_ro_filepath(self._path, stream=False, allow_mmap=True) | ||
| 129 | + try: | ||
| 130 | + self._deserialize(fmap) | ||
| 131 | + finally: | ||
| 132 | + fmap.close() | ||
| 133 | + #END handle closing of handle | ||
| 108 | 134 | ||
| 109 | 135 | #{ Interface | |
| 110 | 136 | ||
@@ -115,14 +141,7 @@ def from_file(cls, filepath): | |||
| 115 | 141 | at the given filepath | |
| 116 | 142 | :param filepath: path to reflog | |
| 117 | 143 | :raise ValueError: If the file could not be read or was corrupted in some way""" | |
| 118 | - inst = cls() | ||
| 119 | - fmap = file_contents_ro_filepath(filepath, stream=False, allow_mmap=True) | ||
| 120 | - try: | ||
| 121 | - inst._deserialize(fmap) | ||
| 122 | - finally: | ||
| 123 | - fmap.close() | ||
| 124 | - #END handle closing of handle | ||
| 125 | - return inst | ||
| 144 | + return cls(filepath) | ||
| 126 | 145 | ||
| 127 | 146 | @classmethod | |
| 128 | 147 | def path(cls, ref): | |
@@ -154,12 +173,35 @@ def iter_entries(cls, stream): | |||
| 154 | 173 | def to_file(self, filepath): | |
| 155 | 174 | """Write the contents of the reflog instance to a file at the given filepath. | |
| 156 | 175 | :param filepath: path to file, parent directories are assumed to exist""" | |
| 176 | + # TODO: Use locked fd | ||
| 157 | 177 | fp = open(filepath, 'wb') | |
| 158 | 178 | try: | |
| 159 | 179 | self._serialize(fp) | |
| 160 | 180 | finally: | |
| 161 | 181 | fp.close() | |
| 162 | 182 | #END handle file streams | |
| 183 | + | ||
| 184 | + def append_entry(self, oldbinsha, newbinsha, message, write=True): | ||
| 185 | + """Append a new log entry to the revlog, changing it in place. | ||
| 186 | + :param oldbinsha: binary sha of the previous commit | ||
| 187 | + :param newbinsha: binary sha of the current commit | ||
| 188 | + :param message: message describing the change to the reference | ||
| 189 | + :param write: If True, the changes will be written right away. Otherwise | ||
| 190 | + the change will not be written | ||
| 191 | + :return: RefLogEntry objects which was appended to the log""" | ||
| 192 | + if len(oldbinsha) != 20 or len(newbinsha) != 20: | ||
| 193 | + raise ValueError("Shas need to be given in binary format") | ||
| 194 | + #END handle sha type | ||
| 195 | + entry = RefLogEntry((bin_to_hex(oldbinsha), bin_to_hex(newbinsha), Actor.committer(), (int(time.time()), time.altzone), message)) | ||
| 196 | + self.append(entry) | ||
| 197 | + if write: | ||
| 198 | + self.write() | ||
| 199 | + #END handle auto-write | ||
| 200 | + return entry | ||
| 201 | + | ||
| 202 | + def write(self): | ||
| 203 | + """Write this instance's data to the file we are originating from""" | ||
| 204 | + return self.to_file(self._path) | ||
| 163 | 205 | ||
| 164 | 206 | #} END interface | |
| 165 | 207 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -236,6 +236,7 @@ def _set_reference(self, ref): | |||
| 236 | 236 | if not isdir(directory): | |
| 237 | 237 | os.makedirs(directory) | |
| 238 | 238 | ||
| 239 | + # TODO: Write using LockedFD | ||
| 239 | 240 | fp = open(path, "wb") | |
| 240 | 241 | try: | |
| 241 | 242 | fp.write(write_value) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | 7 | from git.exc import InvalidGitRepositoryError, NoSuchPathError | |
| 8 | 8 | from git.cmd import Git | |
| 9 | + from git.util import Actor | ||
| 9 | 10 | from git.refs import * | |
| 10 | 11 | from git.index import IndexFile | |
| 11 | 12 | from git.objects import * | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,7 @@ | |||
| 1 | 1 | from git.test.lib import * | |
| 2 | - from git.objects import IndexObject, Actor | ||
| 2 | + from git.objects import IndexObject | ||
| 3 | 3 | from git.refs import * | |
| 4 | + from git.util import Actor | ||
| 4 | 5 | ||
| 5 | 6 | import tempfile | |
| 6 | 7 | import shutil | |
@@ -40,6 +41,7 @@ def test_base(self): | |||
| 40 | 41 | ||
| 41 | 42 | # simple read | |
| 42 | 43 | reflog = RefLog.from_file(rlp_master_ro) | |
| 44 | + assert reflog._path is not None | ||
| 43 | 45 | assert isinstance(reflog, RefLog) | |
| 44 | 46 | assert len(reflog) | |
| 45 | 47 | ||
@@ -56,6 +58,8 @@ def test_base(self): | |||
| 56 | 58 | ||
| 57 | 59 | ||
| 58 | 60 | # test serialize and deserialize - results must match exactly | |
| 61 | + binsha = chr(255)*20 | ||
| 62 | + msg = "my reflog message" | ||
| 59 | 63 | for rlp in (rlp_head, rlp_master): | |
| 60 | 64 | reflog = RefLog.from_file(rlp) | |
| 61 | 65 | tfile = os.path.join(tdir, os.path.basename(rlp)) | |
@@ -67,6 +71,18 @@ def test_base(self): | |||
| 67 | 71 | ||
| 68 | 72 | # ... as well as each bytes of the written stream | |
| 69 | 73 | assert open(tfile).read() == open(rlp).read() | |
| 74 | + | ||
| 75 | + # append an entry - it gets written automatically | ||
| 76 | + entry = treflog.append_entry(IndexObject.NULL_BIN_SHA, binsha, msg) | ||
| 77 | + assert entry.oldhexsha == IndexObject.NULL_HEX_SHA | ||
| 78 | + assert entry.newhexsha == 'f'*40 | ||
| 79 | + assert entry.message == msg | ||
| 80 | + assert treflog == RefLog.from_file(tfile) | ||
| 81 | + | ||
| 82 | + # but not this time | ||
| 83 | + treflog.append_entry(binsha, binsha, msg, write=False) | ||
| 84 | + assert treflog != RefLog.from_file(tfile) | ||
| 85 | + | ||
| 70 | 86 | # END for each reflog | |
| 71 | 87 | ||
| 72 | 88 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,6 +8,7 @@ | |||
| 8 | 8 | from git.test.lib import * | |
| 9 | 9 | from git import * | |
| 10 | 10 | import git.refs as refs | |
| 11 | + from git.util import Actor | ||
| 11 | 12 | from git.objects.tag import TagObject | |
| 12 | 13 | from itertools import chain | |
| 13 | 14 | import os | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,7 +16,7 @@ | |||
| 16 | 16 | import time | |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | - class TestUtils(TestCase): | ||
| 19 | + class TestUtils(TestBase): | ||
| 20 | 20 | def setup(self): | |
| 21 | 21 | self.testdict = { | |
| 22 | 22 | "string": "42", | |
@@ -102,4 +102,8 @@ def assert_rval(rval, veri_time, offset=0): | |||
| 102 | 102 | self.failUnlessRaises(ValueError, parse_date, '123456789 -02000') | |
| 103 | 103 | self.failUnlessRaises(ValueError, parse_date, ' 123456789 -0200') | |
| 104 | 104 | ||
| 105 | - | ||
| 105 | + def test_actor(self): | ||
| 106 | + for cr in (None, self.rorepo.config_reader()): | ||
| 107 | + assert isinstance(Actor.committer(cr), Actor) | ||
| 108 | + assert isinstance(Actor.author(cr), Actor) | ||
| 109 | + #END assure config reader is handled | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments