Skip to content

Commit 096418e

Browse files
author
Daniel B
authored
Merge 6a9295e into f5b93c6
2 parents f5b93c6 + 6a9295e commit 096418e

File tree

16 files changed

+339
-67
lines changed

16 files changed

+339
-67
lines changed

.pylint.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ disable=
125125
too-many-branches,
126126
keyword-arg-before-vararg,
127127
logging-not-lazy,
128+
redefined-builtin,
128129

129130
# Enable the message, report, category or checker with the given id(s). You can
130131
# either give multiple identifier separated by comma (,) or put this option
@@ -268,7 +269,7 @@ indent-after-paren=4
268269
indent-string=' '
269270

270271
# Maximum number of characters on a single line.
271-
max-line-length=79
272+
max-line-length=100
272273

273274
# Maximum number of lines in a module
274275
max-module-lines=1000

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pytest-describe = "*"
2525
pytest-expecter = "*"
2626
pytest-random = "*"
2727
pytest-cov = "*"
28+
pathlib2 = "*"
2829
freezegun = "*"
2930

3031
# Reports

Pipfile.lock

Lines changed: 44 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/setup/git-svn.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Git SVN Setup
2+
3+
## Install missing SVN packages
4+
5+
```shell
6+
sudo apt-get install git-svn
7+
sudo apt-get install subversion libapache2-svn
8+
```
9+
10+
## Credentials
11+
12+
In order for `gitman` to interact with `git svn`, it must be configured to store your SVN credentials (cached) for private repository access.
13+
14+
15+
To test, trying cloning one of your private repositories:
16+
17+
```shell
18+
$ git svn clone -r <rev> <repo>
19+
```
20+
21+
### Option 1: Enter manually credentials
22+
23+
If authentication realm is not already properly configured then Username and Password needs to be entered.
24+
25+
For example:
26+
27+
```shell
28+
$ git svn clone -r HEAD http://my-svn-repo/trunk/MyDirectory
29+
Initialized empty Git repository in /home/Dev/MyDirectory/.git/
30+
Authentication realm: <http://my-svn-repo:80> my-svn-repo repository access
31+
Username: JohnDoe
32+
Password for 'John Doe'
33+
```
34+
35+
This credentials should be cached afterwards.
36+
For further information about caching credentials see [here](http://svnbook.red-bean.com/vi/1.8/svn.serverconfig.netmodel.html).
37+
38+
### Option 2: Manually store Credentials
39+
40+
1. Generate the MD5 hash of the realmstring of the repository provider.
41+
2. Create a file under /home/<username>/.subversion/auth/svn.simple, where the filename is the md5 hash. This is how `git svn` will find the credentials when challenged.
42+
3. The content of the file will have key value pairs as shown below:
43+
44+
```
45+
K 8
46+
passtype
47+
V 6
48+
simple
49+
K 8
50+
password
51+
V <password character count>
52+
<password>
53+
K 15
54+
svn:realmstring
55+
V 50
56+
<repo> <repo name>
57+
K 8
58+
username
59+
V <username character count>
60+
<username>
61+
END
62+
```
63+
64+
4. Now both `git svn` and `svn` should be able to check out from the repo without asking for credentials.

docs/use-cases/git-svn.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Using Git SVN
2+
3+
Many development projects use Subversion (SVN) to manage their source code. It’s the most popular open source VCS and has been around for nearly a decade. It’s also very similar in many ways to CVS, which was the big boy of the source-control world before that.
4+
5+
One of Git’s great features is a bidirectional bridge to Subversion called `git svn`. This tool allows you to use Git as a valid client to a Subversion server, so you can use all the local features of Git and then push to a Subversion server as if you were using Subversion locally.
6+
7+
The gitman git svn support allows you to resolve SVN source dependencies. The gitman does resolve a specified SVN revision (e.g. HEAD) of an SVN repository source dependency (from whole branches to particular subdirectories).
8+
9+
> **Important**
10+
>
11+
> The gitman `git svn` support does currently not track any changes in the imported svn repository.
12+
> The focus of this feature is to just import svn dependencies
13+
> in a readonly fashion.
14+
> In this matter any changes in the imported svn repository
15+
> will be overridden by an update/install process (like an implicit `--force` for each gitman command).
16+
17+
To import svn repositories it is required to specify the repo source parameter `type` to `git-svn` for the corresponding entries.
18+
19+
Example Configuration:
20+
21+
```yaml
22+
location: imports
23+
24+
sources:
25+
- name: MyDirectory
26+
type: git-svn
27+
repo: http:http://my-svn-repo/trunk/MyDirectory
28+
rev: HEAD
29+
30+
- name: MySecondDirectory
31+
type: git-svn
32+
repo: http:http://my-svn-repo/trunk/MySecondDirectory
33+
rev: 72846
34+
35+
- name: lz4
36+
type: git
37+
repo: https://github.com/lz4/lz4
38+
rev: v1.8.1.2
39+
40+
```
41+
42+
By default the repo source parameter `type` is `git`.
43+
44+
> **Note**
45+
>
46+
> The gitman `git svn` support uses internally
47+
> ```shell
48+
> $ git svn clone -r <rev> <repo>
49+
> ```
50+
> to resolve the individual SVN source dependency. In this matter only the specified svn revsion will be fetched (shallow history).
51+
52+

gitman/commands.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ def init():
3434

3535
else:
3636
config = Config()
37-
source = Source(name="sample_dependency",
37+
source = Source('git',
38+
name="sample_dependency",
3839
repo="https://github.com/githubtraining/hellogitworld")
3940
config.sources.append(source)
4041
source = source.lock(rev="ebbbf773431ba07510251bb03f9525c7bab2b13a")

gitman/git.py

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import re
66
from contextlib import suppress
77

8+
import shutil
9+
810
from . import common, settings
911
from .exceptions import ShellError
1012
from .shell import call
@@ -16,11 +18,20 @@
1618
def git(*args, **kwargs):
1719
return call('git', *args, **kwargs)
1820

21+
def gitsvn(*args, **kwargs):
22+
return call('git', 'svn', *args, **kwargs)
1923

20-
def clone(repo, path, *, cache=settings.CACHE, sparse_paths=None, rev=None):
24+
def clone(type, repo, path, *, cache=settings.CACHE, sparse_paths=None, rev=None):
2125
"""Clone a new Git repository."""
2226
log.debug("Creating a new repository...")
2327

28+
if type == 'git-svn':
29+
# just the preperation for the svn deep clone / checkout here (clone will be made in update function to simplify source.py).
30+
os.makedirs(path)
31+
return
32+
33+
assert type == 'git'
34+
2435
name = repo.split('/')[-1]
2536
if name.endswith(".git"):
2637
name = name[:-4]
@@ -50,6 +61,7 @@ def clone(repo, path, *, cache=settings.CACHE, sparse_paths=None, rev=None):
5061
git('clone', '--reference', reference, repo, os.path.normpath(path))
5162

5263

64+
5365
def is_sha(rev):
5466
"""Heuristically determine whether a revision corresponds to a commit SHA.
5567
@@ -60,8 +72,15 @@ def is_sha(rev):
6072
return re.match('^[0-9a-f]{7,40}$', rev) is not None
6173

6274

63-
def fetch(repo, rev=None):
75+
def fetch(type, repo, path, rev=None):
6476
"""Fetch the latest changes from the remote repository."""
77+
78+
if type == 'git-svn':
79+
# deep clone happens in update function
80+
return
81+
82+
assert type == 'git'
83+
6584
git('remote', 'set-url', 'origin', repo)
6685
args = ['fetch', '--tags', '--force', '--prune', 'origin']
6786
if rev:
@@ -86,10 +105,16 @@ def valid():
86105
return True
87106

88107

89-
def changes(include_untracked=False, display_status=True, _show=False):
108+
def changes(type, include_untracked=False, display_status=True, _show=False):
90109
"""Determine if there are changes in the working tree."""
91110
status = False
92111

112+
if type == 'git-svn':
113+
# ignore changes in case of git-svn
114+
return status
115+
116+
assert type == 'git'
117+
93118
try:
94119
# Refresh changes
95120
git('update-index', '-q', '--refresh', _show=False)
@@ -114,7 +139,25 @@ def changes(include_untracked=False, display_status=True, _show=False):
114139
return status
115140

116141

117-
def update(rev, *, clean=True, fetch=False): # pylint: disable=redefined-outer-name
142+
def update(type, repo, path, *, clean=True, fetch=False, rev=None): # pylint: disable=redefined-outer-name
143+
144+
if type == 'git-svn':
145+
# make deep clone here for simplification of sources.py
146+
# and to realize consistent readonly clone (always forced)
147+
148+
# completly empty current directory (remove also hidden content)
149+
for root, dirs, files in os.walk('.'):
150+
for f in files:
151+
os.unlink(os.path.join(root, f))
152+
for d in dirs:
153+
shutil.rmtree(os.path.join(root, d))
154+
155+
# clone specified svn revision
156+
gitsvn('clone', '-r', rev, repo, '.')
157+
return
158+
159+
assert type == 'git'
160+
118161
"""Update the working tree to the specified revision."""
119162
hide = {'_show': False, '_ignore': True}
120163

@@ -131,21 +174,40 @@ def update(rev, *, clean=True, fetch=False): # pylint: disable=redefined-outer-
131174
git('pull', '--ff-only', '--no-rebase', **hide)
132175

133176

134-
def get_url():
177+
def get_url(type):
135178
"""Get the current repository's URL."""
179+
if type == 'git-svn':
180+
return git('config', '--get', 'svn-remote.svn.url', _show=False)[0]
181+
182+
assert type == 'git'
183+
136184
return git('config', '--get', 'remote.origin.url', _show=False)[0]
137185

138186

139-
def get_hash(_show=False):
187+
def get_hash(type, _show=False):
140188
"""Get the current working tree's hash."""
189+
if type == 'git-svn':
190+
return ''.join(filter(str.isdigit, gitsvn('info', _show=_show)[4]))
191+
192+
assert type == 'git'
193+
141194
return git('rev-parse', 'HEAD', _show=_show)[0]
142195

143-
144196
def get_tag():
145197
"""Get the current working tree's tag (if on a tag)."""
146198
return git('describe', '--tags', '--exact-match',
147199
_show=False, _ignore=True)[0]
148200

201+
def is_fetch_required(type, rev):
202+
if type == 'git-svn':
203+
return False
204+
205+
assert type == 'git'
206+
207+
return rev not in (get_branch(),
208+
get_hash(type),
209+
get_tag())
210+
149211

150212
def get_branch():
151213
"""Get the current working tree's branch."""

0 commit comments

Comments
 (0)