Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit 848a3d3

Browse files
committed
Merge branch 'develop'
2 parents fa418b1 + c2e304a commit 848a3d3

File tree

13 files changed

+163
-245
lines changed

13 files changed

+163
-245
lines changed

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
gitpylib
22
=========
33

4+
[![PyPI version](https://badge.fury.io/py/gitpylib.svg)](
5+
http://badge.fury.io/py/gitpylib)
6+
47
Python library for Git.
58

6-
Has methods for the most frequently used Git features; abstracts the user of the
7-
library from the burden of having to know which is the correct command to use to
8-
perform some Git operation.
9+
gitpylib is a lightweight wrapper of the `git` command.
10+
11+
**As of 02/2015 gitpylib has been phased out and merged into
12+
[Gitless](https://github.com/sdg-mit/gitless "Gitless").**
13+
14+
Install
15+
-------
16+
17+
Via `pip` (the Python Package Manager):
18+
19+
$> pip install gitless

RELEASE_NOTES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ Gitpylib's Release Notes
22
========================
33

44

5+
10th Feb 2015 - 0.7
6+
-------------------
7+
8+
* Bug fixes.
9+
10+
511
25th Mar 2014 - 0.6
612
-------------------
713

gitpylib/branch.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
"""Module for dealing with Git branches."""
55

66

7+
import collections
78
import re
89

910
from . import common
1011

1112

13+
BranchStatus = collections.namedtuple(
14+
'BranchStatus', ['name', 'is_current', 'tracks'])
15+
1216
SUCCESS = 1
1317
UNFETCHED_OBJECT = 2
1418
INVALID_NAME = 3
@@ -26,7 +30,7 @@ def checkout(name):
2630
Returns:
2731
SUCCESS or NONEXISTENT_BRANCH
2832
"""
29-
ok, _, _ = common.git_call('checkout %s' % name)
33+
ok, _, _ = common.git_call('checkout {0}'.format(name))
3034
if not ok:
3135
return NONEXISTENT_BRANCH
3236
return SUCCESS
@@ -63,7 +67,7 @@ def force_delete(name):
6367
Returns:
6468
SUCCESS or NONEXISTENT_BRANCH
6569
"""
66-
ok, _, _ = common.git_call('branch -D %s' % name)
70+
ok, _, _ = common.git_call('branch -D {0}'.format(name))
6771
if not ok:
6872
return NONEXISTENT_BRANCH
6973
return SUCCESS
@@ -83,27 +87,26 @@ def status(name):
8387
name: the name of the branch to status.
8488
8589
Returns:
86-
a tuple (exists, is_current, tracks) where exists and is_current are
87-
boolean values and tracks is a string representing the remote branch it
88-
tracks (in the format 'remote_name/remote_branch') or None if it is a local
89-
branch.
90+
None if the branch doesn't exist or a namedtuple (name, is_current, tracks)
91+
where is_current is a boolean value and tracks is a string representing the
92+
remote branch it tracks (in the format 'remote_name/remote_branch') or None
93+
if it is a local branch.
9094
"""
91-
out, _ = common.safe_git_call('branch --list -vv %s' % name)
95+
out, _ = common.safe_git_call('branch --list -vv {0}'.format(name))
9296
if not out:
93-
return (False, False, None)
97+
return None
9498

95-
_, is_current, tracks = _parse_output(out)
96-
return (True, is_current, tracks)
99+
return _parse_output(out)
97100

98101

99102
def status_all():
100103
"""Get the status of all existing branches.
101104
102105
Yields:
103-
tuples of the form (name, is_current, tracks) where is_current is a boolean
104-
value and tracks is a string representing the remote branch it tracks (in
105-
the format 'remote_name/remote_branch') or None if it is a local branch.
106-
name could be equal to '(no branch)' if the user is in no branch.
106+
namedtuples of the form (name, is_current, tracks) where is_current is a
107+
boolean value and tracks is a string representing the remote branch it
108+
tracks (in the format 'remote_name/remote_branch') or None if it is a local
109+
branch. name could be equal to '(no branch)' if the user is in no branch.
107110
"""
108111
out, _ = common.safe_git_call('branch --list -vv')
109112
for b in out.splitlines():
@@ -118,7 +121,7 @@ def set_upstream(branch, upstream_branch):
118121
upstream_branch: the upstream branch.
119122
"""
120123
ok, _, _ = common.git_call(
121-
'branch --set-upstream %s %s' % (branch, upstream_branch))
124+
'branch --set-upstream {0} {1}'.format(branch, upstream_branch))
122125

123126
if not ok:
124127
return UNFETCHED_OBJECT
@@ -132,7 +135,7 @@ def unset_upstream(branch):
132135
Args:
133136
branch: the branch to unset its upstream.
134137
"""
135-
common.git_call('branch --unset-upstream %s' % branch)
138+
common.git_call('branch --unset-upstream {0}'.format(branch))
136139
return SUCCESS
137140

138141

@@ -151,7 +154,7 @@ def _parse_output(out):
151154
# the branch followed by the sha1, optionally followed by some remote tracking
152155
# info (between brackets) and finally the message of the last commit.
153156
if out.startswith('* (no branch)'):
154-
return ('(no branch)', True, None)
157+
return BranchStatus('(no branch)', True, None)
155158

156159
pattern = r'([\*| ]) ([^\s]+)[ ]+\w+ (.+)'
157160
result = re.match(pattern, out)
@@ -166,4 +169,4 @@ def _parse_output(out):
166169
tracks = track_info.split(':')[0]
167170
else:
168171
tracks = track_info
169-
return (result.group(2), result.group(1) == '*', tracks)
172+
return BranchStatus(result.group(2), result.group(1) == '*', tracks)

gitpylib/common.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ def safe_git_call(cmd):
3737
ok, out, err = git_call(cmd)
3838
if ok:
3939
return out, err
40-
raise Exception('%s failed: out is %s, err is %s' % (cmd, out, err))
40+
raise Exception('{0} failed: out is {1}, err is {2}'.format(cmd, out, err))
4141

4242

4343
def git_call(cmd):
4444
p = subprocess.Popen(
45-
shlex.split('git %s' % cmd),
45+
shlex.split('git {0}'.format(cmd)),
4646
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
4747
out, err = p.communicate()
4848
# Python 2/3 compatibility.
@@ -76,10 +76,8 @@ def real_case(fp):
7676
found = True
7777
break
7878
if not found:
79-
# TODO(sperezde): fix this hack
80-
# raise Exception("Invalid file %s: the file doesn't exist" % fp)
81-
# Temp hack until I figure out how to deal with filenames with special
82-
# characters.
79+
# TODO(sperezde): fix this hack (deal with filenames with special
80+
# characters).
8381
return fp
8482
return os.path.join(*ret)
8583

@@ -116,17 +114,15 @@ def remove_dups(list, key):
116114
list: the list to read from.
117115
key: a function that receives an element from list and returns its key.
118116
119-
Returns:
120-
a new list without duplicates.
117+
Yields:
118+
unique elements of the given list
121119
"""
122120
keys = set()
123-
ret = []
124121
for a in list:
125122
k_a = key(a)
126123
if k_a not in keys:
127124
keys.add(k_a)
128-
ret.append(a)
129-
return ret
125+
yield a
130126

131127

132128
def get_all_fps_under_cwd():
@@ -140,3 +136,11 @@ def get_all_fps_under_cwd():
140136
dirnames.remove('.git')
141137
for fp in filenames:
142138
yield os.path.relpath(os.path.join(dirpath, fp))
139+
140+
141+
def items(dic):
142+
"""Py 2/3 compatible way of getting the items of a dictionary."""
143+
try:
144+
return dic.iteritems()
145+
except AttributeError:
146+
return iter(dic.items())

gitpylib/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88

99

1010
def get(var):
11-
ok, out, _ = common.git_call('config %s' % var)
11+
ok, out, _ = common.git_call('config {0}'.format(var))
1212
return out.strip() if ok else None

gitpylib/file.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def stage(fp):
3737

3838
fp = common.real_case(fp)
3939

40-
common.safe_git_call('add "%s"' % fp)
40+
common.safe_git_call('add "{0}"'.format(fp))
4141
return SUCCESS
4242

4343

@@ -58,7 +58,7 @@ def unstage(fp):
5858
# http://comments.gmane.org/gmane.comp.version-control.git/211242.
5959
# So, we need to ignore the return code (unfortunately) and hope that it
6060
# works.
61-
common.git_call('reset HEAD "%s"' % fp)
61+
common.git_call('reset HEAD "{0}"'.format(fp))
6262
return SUCCESS
6363

6464

@@ -75,12 +75,12 @@ def show(fp, cp):
7575
"""
7676
fp = common.real_case(fp)
7777

78-
ok, out, _ = common.git_call('show %s:"%s"' % (cp, fp))
78+
ok, out, _ = common.git_call('show {0}:"{1}"'.format(cp, fp))
7979

8080
if not ok:
81-
return (FILE_NOT_FOUND_AT_CP, None)
81+
return FILE_NOT_FOUND_AT_CP, None
8282

83-
return (SUCCESS, out)
83+
return SUCCESS, out
8484

8585

8686
def assume_unchanged(fp):
@@ -94,7 +94,7 @@ def assume_unchanged(fp):
9494
"""
9595
fp = common.real_case(fp)
9696

97-
common.safe_git_call('update-index --assume-unchanged "%s"' % fp)
97+
common.safe_git_call('update-index --assume-unchanged "{0}"'.format(fp))
9898
return SUCCESS
9999

100100

@@ -109,7 +109,7 @@ def not_assume_unchanged(fp):
109109
"""
110110
fp = common.real_case(fp)
111111

112-
common.safe_git_call('update-index --no-assume-unchanged "%s"' % fp)
112+
common.safe_git_call('update-index --no-assume-unchanged "{0}"'.format(fp))
113113
return SUCCESS
114114

115115

@@ -137,14 +137,15 @@ def diff(fp, staged=False):
137137
fp = common.real_case(fp)
138138

139139
st = '--cached' if staged else ''
140-
out, _ = common.safe_git_call('diff %s -- "%s"' % (st, fp))
140+
out, _ = common.safe_git_call('diff {0} -- "{1}"'.format(st, fp))
141141
if not out:
142-
return ([], 0, 0, 0, None)
143-
stats_out, _ = common.safe_git_call('diff %s --numstat -- "%s"' % (st, fp))
142+
return [], 0, 0, 0, None
143+
stats_out, _ = common.safe_git_call(
144+
'diff {0} --numstat -- "{1}"'.format(st, fp))
144145
header, body = _split_diff(out.splitlines())
145146
line, padding = _process_diff_output(body)
146147
additions, removals = _process_diff_stats_output(stats_out)
147-
return (line, padding, additions, removals, header)
148+
return line, padding, additions, removals, header
148149

149150

150151
# Private functions.
@@ -206,4 +207,4 @@ def _process_diff_output(diff_out):
206207
def _process_diff_stats_output(diff_stats_out):
207208
# format is additions tab removals.
208209
m = re.match(r'([0-9]+)\t([0-9]+)', diff_stats_out)
209-
return (int(m.group(1)), int(m.group(2)))
210+
return int(m.group(1)), int(m.group(2))

gitpylib/log.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from . import file as git_file
1010

1111

12-
# TODO: add more info like parents, tree, committer, etc.
1312
Commit = collections.namedtuple(
1413
'Commit', ['id', 'author', 'msg', 'diffs'])
1514

@@ -19,6 +18,7 @@
1918
CommitDiff = collections.namedtuple(
2019
'CommitDiff', ['fp_before', 'fp_after', 'diff'])
2120

21+
2222
def log(include_diffs=False):
2323
log_fmt = r'[[%H] [%an] [%ae] [%aD] [%ar]]%n%B'
2424
out, _ = common.safe_git_call(

gitpylib/remote.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ def add(remote_name, remote_url):
3030
"""
3131
if _show(remote_url)[0] == REMOTE_UNREACHABLE:
3232
return REMOTE_UNREACHABLE
33-
common.safe_git_call('remote add %s %s' % (remote_name, remote_url))
34-
common.safe_git_call('fetch %s' % remote_name)
33+
common.safe_git_call('remote add {0} {1}'.format(remote_name, remote_url))
34+
common.safe_git_call('fetch {0}'.format(remote_name))
3535
return SUCCESS
3636

3737

@@ -46,7 +46,7 @@ def show(remote_name):
4646
REMOTE_UNREACHABLE and out is the output of the show command on success.
4747
"""
4848
if remote_name not in show_all():
49-
return (REMOTE_NOT_FOUND, None)
49+
return REMOTE_NOT_FOUND, None
5050
return _show(remote_name)
5151

5252

@@ -81,15 +81,15 @@ def show_all_v():
8181

8282

8383
def rm(remote_name):
84-
common.safe_git_call('remote rm %s' % remote_name)
84+
common.safe_git_call('remote rm {0}'.format(remote_name))
8585

8686

8787
def head_exist(remote_name, head):
8888
ok, out, _ = common.git_call(
89-
'ls-remote --heads %s %s' % (remote_name, head))
89+
'ls-remote --heads {0} {1}'.format(remote_name, head))
9090
if not ok:
91-
return (False, REMOTE_UNREACHABLE)
92-
return (len(out) > 0, REMOTE_BRANCH_NOT_FOUND)
91+
return False, REMOTE_UNREACHABLE
92+
return len(out) > 0, REMOTE_BRANCH_NOT_FOUND
9393

9494

9595
def branches(remote_name):
@@ -108,9 +108,9 @@ def branches(remote_name):
108108

109109

110110
def _show(remote):
111-
ok, out, err = common.git_call('remote show %s' % remote)
111+
ok, out, err = common.git_call('remote show {0}'.format(remote))
112112
if not ok:
113113
if 'fatal: Could not read from remote repository' in err:
114-
return (REMOTE_UNREACHABLE, None)
114+
return REMOTE_UNREACHABLE, None
115115
raise common.UnexpectedOutputError('remote', out, err=err)
116-
return (SUCCESS, out)
116+
return SUCCESS, out

gitpylib/repo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
def clone(repo):
99
"""Returns True if the clone succeeded, False if otherwise."""
10-
return common.git_call('clone %s .' % repo)[0]
10+
return common.git_call('clone {0} .'.format(repo))[0]
1111

1212

1313
def init():

0 commit comments

Comments
 (0)