Skip to content

Commit 3175b5b

Browse files
committed
Merge branch 'reflog'
2 parents fca3675 + 3203cd7 commit 3175b5b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2511
-1225
lines changed

__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ def _init_externals():
3737
from git.util import (
3838
LockFile,
3939
BlockingLockFile,
40-
Stats
40+
Stats,
41+
Actor
4142
)
4243

4344
#} END imports

doc/source/changes.rst

+31-2
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,45 @@
22
Changelog
33
=========
44

5-
0.3.2 Beta 1
5+
0.3.1 Beta 2
66
============
7-
* Flattened directory structure to make development more convenient.
7+
* Added **reflog support** ( reading and writing )
8+
9+
* New types: ``RefLog`` and ``RefLogEntry``
10+
* Reflog is maintained automatically when creating references and deleting them
11+
* Non-intrusive changes to ``SymbolicReference``, these don't require your code to change. They allow to append messages to the reflog.
12+
13+
* ``abspath`` property added, similar to ``abspath`` of Object instances
14+
* ``log()`` method added
15+
* ``log_append(...)`` method added
16+
* ``set_reference(...)`` method added (reflog support)
17+
* ``set_commit(...)`` method added (reflog support)
18+
* ``set_object(...)`` method added (reflog support)
19+
20+
* Intrusive Changes to ``Head`` type
21+
22+
* ``create(...)`` method now supports the reflog, but will not raise ``GitCommandError`` anymore as it is a pure python implementation now. Instead, it raises ``OSError``.
23+
24+
* Repo.rev_parse now supports the [ref]@{n} syntax, where n is the number of steps to look into the reference's past
25+
26+
* **BugFixes**
27+
28+
* Removed incorrect ORIG_HEAD handling
29+
30+
* **Flattened directory** structure to make development more convenient.
831

932
* .. note:: This alters the way projects using git-python as a submodule have to adjust their sys.path to be able to import git-python successfully.
33+
* Misc smaller changes and bugfixes
1034

1135
0.3.1 Beta 1
1236
============
1337
* Full Submodule-Support
1438
* Added unicode support for author names. Commit.author.name is now unicode instead of string.
39+
* Head Type changes
40+
41+
* config_reader() & config_writer() methods added for access to head specific options.
42+
* tracking_branch() & set_tracking_branch() methods addded for easy configuration of tracking branches.
43+
1544

1645
0.3.0 Beta 2
1746
============

doc/source/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# is relative to the documentation root, use os.path.abspath to make it
2121
# absolute, like shown here.
2222
#sys.path.append(os.path.abspath('.'))
23-
sys.path.insert(0, os.path.abspath('../../lib'))
23+
sys.path.insert(0, os.path.abspath('../../../'))
2424

2525
# General configuration
2626
# ---------------------

doc/source/reference.rst

+38-3
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,48 @@ Exceptions
131131
:undoc-members:
132132

133133

134-
Refs
135-
----
134+
Refs.symbolic
135+
-------------
136+
137+
.. automodule:: git.refs.symbolic
138+
:members:
139+
:undoc-members:
140+
141+
Refs.reference
142+
--------------
136143

137-
.. automodule:: git.refs
144+
.. automodule:: git.refs.reference
138145
:members:
139146
:undoc-members:
140147

148+
Refs.head
149+
---------
150+
151+
.. automodule:: git.refs.head
152+
:members:
153+
:undoc-members:
154+
155+
Refs.tag
156+
------------
157+
158+
.. automodule:: git.refs.tag
159+
:members:
160+
:undoc-members:
161+
162+
Refs.remote
163+
------------
164+
165+
.. automodule:: git.refs.remote
166+
:members:
167+
:undoc-members:
168+
169+
Refs.log
170+
------------
171+
172+
.. automodule:: git.refs.log
173+
:members:
174+
:undoc-members:
175+
141176
Remote
142177
------
143178

doc/source/tutorial.rst

+8
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ A symbolic reference is a special case of a reference as it points to another re
8888
head = repo.head # the head points to the active branch/ref
8989
master = head.reference # retrieve the reference the head points to
9090
master.commit # from here you use it as any other reference
91+
92+
Access the reflog easily::
93+
94+
log = master.log()
95+
log[0] # first (i.e. oldest) reflog entry
96+
log[-1] # last (i.e. most recent) reflog entry
97+
98+
For more information on the reflog, see the ``RefLog`` type's documentation.
9199

92100
Modifying References
93101
********************

index/base.py

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
#
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
6-
"""Module containing Index implementation, allowing to perform all kinds of index
7-
manipulations such as querying and merging."""
86
import tempfile
97
import os
108
import sys

index/fun.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
"""
2-
Contains standalone functions to accompany the index implementation and make it
3-
more versatile
4-
"""
1+
# Contains standalone functions to accompany the index implementation and make it
2+
# more versatile
3+
# NOTE: Autodoc hates it if this is a docstring
54
from stat import (
65
S_IFDIR,
76
S_IFLNK,

objects/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# imported by the submodule.base
88
import submodule.util
99
submodule.util.IndexObject = IndexObject
10+
submodule.util.Object = Object
1011
from submodule.base import *
1112
from submodule.root import *
1213

@@ -15,7 +16,6 @@
1516
from blob import *
1617
from commit import *
1718
from tree import *
18-
from util import Actor
1919

2020
__all__ = [ name for name, obj in locals().items()
2121
if not (name.startswith('_') or inspect.ismodule(obj)) ]

objects/base.py

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ def new_from_sha(cls, repo, sha1):
5757
:return: new object instance of a type appropriate to represent the given
5858
binary sha1
5959
:param sha1: 20 byte binary sha1"""
60+
if sha1 == cls.NULL_BIN_SHA:
61+
# the NULL binsha is always the root commit
62+
return get_object_type_by_name('commit')(repo, sha1)
63+
#END handle special case
6064
oinfo = repo.odb.info(sha1)
6165
inst = get_object_type_by_name(oinfo.type)(repo, oinfo.binsha)
6266
inst.size = oinfo.size

objects/commit.py

+4-23
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

7-
from git.util import (
7+
from git.util import (
8+
Actor,
89
Iterable,
910
Stats,
1011
)
@@ -20,9 +21,7 @@
2021
from util import (
2122
Traversable,
2223
Serializable,
23-
get_user_id,
2424
parse_date,
25-
Actor,
2625
altz_to_utctz_str,
2726
parse_actor_and_date
2827
)
@@ -43,17 +42,10 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable):
4342

4443
# ENVIRONMENT VARIABLES
4544
# read when creating new commits
46-
env_author_name = "GIT_AUTHOR_NAME"
47-
env_author_email = "GIT_AUTHOR_EMAIL"
4845
env_author_date = "GIT_AUTHOR_DATE"
49-
env_committer_name = "GIT_COMMITTER_NAME"
50-
env_committer_email = "GIT_COMMITTER_EMAIL"
5146
env_committer_date = "GIT_COMMITTER_DATE"
52-
env_email = "EMAIL"
5347

5448
# CONFIGURATION KEYS
55-
conf_name = 'name'
56-
conf_email = 'email'
5749
conf_encoding = 'i18n.commitencoding'
5850

5951
# INVARIANTS
@@ -306,17 +298,9 @@ def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False):
306298
# COMMITER AND AUTHOR INFO
307299
cr = repo.config_reader()
308300
env = os.environ
309-
default_email = get_user_id()
310-
default_name = default_email.split('@')[0]
311301

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

321305
# PARSE THE DATES
322306
unix_time = int(time())
@@ -340,9 +324,6 @@ def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False):
340324
enc_section, enc_option = cls.conf_encoding.split('.')
341325
conf_encoding = cr.get_value(enc_section, enc_option, cls.default_encoding)
342326

343-
author = Actor(author_name, author_email)
344-
committer = Actor(committer_name, committer_email)
345-
346327

347328
# if the tree is no object, make sure we create one - otherwise
348329
# the created commit object is invalid

objects/submodule/base.py

+2-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
join_path_native,
1515
to_native_path_linux
1616
)
17+
1718
from git.config import SectionConstraint
1819
from git.exc import (
1920
InvalidGitRepositoryError,
@@ -339,14 +340,7 @@ def update(self, recursive=False, init=True, to_latest_revision=False):
339340

340341
# have a valid branch, but no checkout - make sure we can figure
341342
# that out by marking the commit with a null_sha
342-
# have to write it directly as .commit = NULLSHA tries to resolve the sha
343-
# This will bring the branch into existance
344-
refpath = join_path_native(mrepo.git_dir, local_branch.path)
345-
refdir = os.path.dirname(refpath)
346-
if not os.path.isdir(refdir):
347-
os.makedirs(refdir)
348-
#END handle directory
349-
open(refpath, 'w').write(self.NULL_HEX_SHA)
343+
local_branch.set_object(util.Object(mrepo, self.NULL_BIN_SHA))
350344
# END initial checkout + branch creation
351345

352346
# make sure HEAD is not detached

objects/submodule/root.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
4848
4949
:param previous_commit: If set to a commit'ish, the commit we should use
5050
as the previous commit the HEAD pointed to before it was set to the commit it points to now.
51-
If None, it defaults to ORIG_HEAD otherwise, or the parent of the current
52-
commit if it is not given
51+
If None, it defaults to HEAD@{1} otherwise
5352
:param recursive: if True, the children of submodules will be updated as well
5453
using the same technique
5554
:param force_remove: If submodules have been deleted, they will be forcibly removed.

objects/util.py

+8-67
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66
"""Module for general utility functions"""
7-
from git.util import IterableList
7+
from git.util import (
8+
IterableList,
9+
Actor
10+
)
811

912
import re
1013
from collections import deque as Deque
11-
import platform
1214

1315
from string import digits
1416
import time
1517
import os
1618

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',
1820
'ProcessStreamAdapter', 'Traversable', 'altz_to_utctz_str', 'utctz_to_altz',
19-
'verify_utctz')
21+
'verify_utctz', 'Actor')
2022

2123
#{ Functions
2224

@@ -57,21 +59,9 @@ def get_object_type_by_name(object_type_name):
5759
else:
5860
raise ValueError("Cannot handle unknown object type: %s" % object_type_name)
5961

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-
7262
def utctz_to_altz(utctz):
7363
"""we convert utctz to the timezone in seconds, it is the format time.altzone
74-
returns. Git stores it as UTC timezon which has the opposite sign as well,
64+
returns. Git stores it as UTC timezone which has the opposite sign as well,
7565
which explains the -1 * ( that was made explicit here )
7666
:param utctz: git utc timezone string, i.e. +0200"""
7767
return -1 * int(float(utctz)/100*3600)
@@ -193,56 +183,6 @@ def parse_actor_and_date(line):
193183

194184

195185
#{ 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-
def __init__(self, name, email):
206-
self.name = name
207-
self.email = email
208-
209-
def __eq__(self, other):
210-
return self.name == other.name and self.email == other.email
211-
212-
def __ne__(self, other):
213-
return not (self == other)
214-
215-
def __hash__(self):
216-
return hash((self.name, self.email))
217-
218-
def __str__(self):
219-
return self.name
220-
221-
def __repr__(self):
222-
return '<git.Actor "%s <%s>">' % (self.name, self.email)
223-
224-
@classmethod
225-
def _from_string(cls, string):
226-
"""Create an Actor from a string.
227-
:param string: is the string, which is expected to be in regular git format
228-
229-
John Doe <jdoe@example.com>
230-
231-
:return: Actor """
232-
m = cls.name_email_regex.search(string)
233-
if m:
234-
name, email = m.groups()
235-
return Actor(name, email)
236-
else:
237-
m = cls.name_only_regex.search(string)
238-
if m:
239-
return Actor(m.group(1), None)
240-
else:
241-
# assume best and use the whole string as name
242-
return Actor(string, None)
243-
# END special case name
244-
# END handle name/email matching
245-
246186

247187
class ProcessStreamAdapter(object):
248188
"""Class wireing all calls to the contained Process instance.
@@ -359,6 +299,7 @@ def addToStack( stack, item, branch_first, depth ):
359299

360300
class Serializable(object):
361301
"""Defines methods to serialize and deserialize objects from and into a data stream"""
302+
__slots__ = tuple()
362303

363304
def _serialize(self, stream):
364305
"""Serialize the data of this object into the given data stream

0 commit comments

Comments
 (0)