Skip to content
This repository was archived by the owner on Oct 7, 2022. It is now read-only.

Commit 49d7bdb

Browse files
committed
Add support for "-e hg+URI" style dependencies
initial work was done by @seppeljordan in #101 then I (@garbas): - rebased on current master - added support for pinning repositories to branch/revision - used https://bitbucket.org/tarek/flake8 as example repository fixes #100 fixes #101
1 parent f64e34f commit 49d7bdb

File tree

8 files changed

+133
-16
lines changed

8 files changed

+133
-16
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ env:
99
- EXAMPLE=empy
1010
- EXAMPLE=ldap
1111
- EXAMPLE=lektor
12+
- EXAMPLE=mercurial
1213
- EXAMPLE=rss2email
1314
- EXAMPLE=scipy
1415
- EXAMPLE=tornado
@@ -20,6 +21,9 @@ matrix:
2021
- os: osx
2122
env: EXAMPLE=scipy
2223
before_install:
24+
- nix-env -iA nixpkgs.cacert -p result-cacert
25+
- export SSL_CERT_FILE=$PWD/result-cacert/etc/ssl/certs/ca-bundle.crt
26+
- sudo mkdir -p /etc/ssl/certs/ && sudo rm -f /etc/ssl/certs/ca-certificates.crt && sudo ln -s $PWD/result-cacert/etc/ssl/certs/ca-bundle.crt /etc/ssl/certs/ca-certificates.crt
2327
- echo 'binary-caches = https://cache.nixos.org/ https://travis.garbas.si/pypi2nix/' | sudo tee -a /etc/nix/nix.conf > /dev/null
2428
- openssl aes-256-cbc -K $encrypted_0cfcc1944c73_key -iv $encrypted_0cfcc1944c73_iv -in deploy_rsa.enc -out deploy_rsa -d
2529
- eval "$(ssh-agent -s)"

default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ in stdenv.mkDerivation rec {
4444
patchPhase = ''
4545
sed -i -e "s|default='nix-shell',|default='${nix.out}/bin/nix-shell',|" $out/pkgs/pypi2nix/cli.py
4646
sed -i -e "s|nix-prefetch-git|${nix-prefetch-scripts}/bin/nix-prefetch-git|" $out/pkgs/pypi2nix/stage2.py
47+
sed -i -e "s|nix-prefetch-hg|${nix-prefetch-scripts}/bin/nix-prefetch-hg|" $out/pkgs/pypi2nix/stage2.py
4748
'';
4849

4950
commonPhase = ''

examples/Makefile

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,24 @@ else
1010
LEKTOR_BUILD_INPUTS="libffi openssl unzip"
1111
endif
1212

13+
.PHONY: \
14+
awscli_and_requests \
15+
empy \
16+
ldap \
17+
lektor \
18+
mercurial \
19+
rss2email \
20+
scipy \
21+
sentry \
22+
tornado \
23+
vulnix
1324

14-
# commented out sentry since it doesn't work on travis
1525
all: \
1626
awscli_and_requests \
1727
empy \
1828
ldap \
1929
lektor \
30+
mercurial \
2031
rss2email \
2132
scipy \
2233
sentry \
@@ -26,8 +37,9 @@ all: \
2637
clear: \
2738
awscli_and_requests-clear \
2839
empy-clear \
29-
ldap_clear \
40+
ldap-clear \
3041
lektor-clear \
42+
mercurial-clear \
3143
pypi2nix-clear \
3244
rss2email-clear \
3345
scipy-clear \
@@ -227,6 +239,10 @@ tornado: tornado.nix
227239
@nix-build tornado.nix -o tornado -A interpreter --show-trace
228240
@./tornado/bin/python -c 'import tornado'
229241
@nix-shell tornado.nix -A interpreter --run "python -c 'import tornado'"
242+
@if [ `cat tornado_generated.nix | grep "69253c820df473407c562a227d0ba36df25018ab" | wc -l` != "1" ]; then \
243+
echo "ERROR: Revision '69253c820df473407c562a227d0ba36df25018ab' not found in tornado_generated.nix!"; \
244+
exit 123; \
245+
fi
230246

231247
tornado.nix: tornado.txt $(PYPI2NIX)
232248
@echo "generating tornado.nix expressions ..."
@@ -270,3 +286,31 @@ ldap-clear:
270286
@rm -f ldap.nix
271287
@rm -f ldap_generated.nix
272288
@rm -f ldap_frozen.txt
289+
290+
291+
mercurial: mercurial.nix
292+
@echo "building and testing mercurial..."
293+
@nix-build mercurial.nix -o mercurial -A interpreter --show-trace -j 1
294+
@./mercurial/bin/python -c 'import flake8'
295+
@nix-shell mercurial.nix -A interpreter --run "python -c 'import flake8'"
296+
@if [ `cat mercurial_generated.nix | grep "a209fb6" | wc -l` != "1" ]; then \
297+
echo "ERROR: Revision 'a209fb6' not found in tornado_generated.nix!"; \
298+
exit 123; \
299+
fi
300+
301+
mercurial.nix: mercurial.txt $(PYPI2NIX)
302+
@echo "generating mercurial.nix expressions ..."
303+
@$(PYPI2NIX) -v --basename mercurial -r mercurial.txt -I $(NIX_PATH) -V "2.7" -E "mercurial"
304+
305+
306+
mercurial.txt: mercurial-clear
307+
@echo "-e hg+https://bitbucket.org/tarek/flake8@a209fb6#egg=flake8" > mercurial.txt
308+
@echo "pytest-runner" >> mercurial.txt
309+
@echo "setuptools-scm" >> mercurial.txt
310+
311+
mercurial-clear:
312+
@rm -f mercurial
313+
@rm -f mercurial.txt
314+
@rm -f mercurial.nix
315+
@rm -f mercurial_generated.nix
316+
@rm -f mercurial_frozen.txt

examples/mercurial_override.nix

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{ pkgs, python }:
2+
3+
self: super: {
4+
5+
"pyflakes" = python.overrideDerivation super."pyflakes" (old: {
6+
buildInputs = [ self."pytest-runner" ];
7+
});
8+
9+
"mccabe" = python.overrideDerivation super."mccabe" (old: {
10+
buildInputs = [ self."pytest-runner" ];
11+
});
12+
13+
"pytest-runner" = python.overrideDerivation super."pytest-runner" (old: {
14+
buildInputs = [ self."setuptools-scm" ];
15+
});
16+
}

src/pypi2nix/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ def handle_requirements_file(project_dir, requirements_file):
192192
with open(requirements_file) as f1:
193193
with open(new_requirements_file, "w+") as f2:
194194
for requirements_line in f1.readlines():
195-
if requirements_line.startswith("-e git+"):
195+
if requirements_line.startswith("-e git+") or \
196+
requirements_line.startswith("-e hg+"):
196197
pass
197198
elif requirements_line.startswith("-e"):
198199
requirements_line = "-e %s" % (

src/pypi2nix/stage2.py

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,6 @@ def find_release(wheel_cache_dir, wheel, wheel_data):
258258
break
259259

260260
if not wheel_release:
261-
import pdb
262-
pdb.set_trace()
263261
raise click.ClickException(
264262
"Unable to find release for package {name} of version "
265263
"{version}".format(**wheel))
@@ -285,17 +283,20 @@ def find_release(wheel_cache_dir, wheel, wheel_data):
285283
return release
286284

287285

288-
def process_wheel(wheel_cache_dir, wheel, sources, verbose, index=INDEX_URL,
289-
chunk_size=2048):
286+
def process_wheel(wheel_cache_dir, wheel, sources, repo_types, verbose,
287+
index=INDEX_URL, chunk_size=2048):
290288
"""
291289
"""
292290

291+
repo_type = repo_types.get(wheel['name'], None)
293292
if wheel['name'] in sources:
294293
release = dict()
295294
release['url'] = sources[wheel['name']]
296295
release['hash_type'] = 'sha256'
297296

298-
if release['url'].startswith('http://') or release['url'].startswith('https://'):
297+
if repo_type is None and \
298+
(release['url'].startswith('http://') or \
299+
release['url'].startswith('https://')):
299300

300301
release['fetch_type'] = 'fetchurl'
301302

@@ -309,16 +310,18 @@ def process_wheel(wheel_cache_dir, wheel, sources, verbose, index=INDEX_URL,
309310
hash = hashlib.sha256(fd.read())
310311

311312
release['hash_value'] = hash.hexdigest()
312-
elif release['url'].startswith('git'):
313+
314+
elif repo_type == 'git':
313315
revision = ''
314316
if release['url'].startswith('git+'):
315317
release['url'] = release['url'][4:]
316318
if '@' in release['url']:
317319
release['url'], revision = release['url'].split('@')
320+
318321
release['fetch_type'] = 'fetchgit'
319322
command = 'nix-prefetch-git {url} {revision}'.format(
320323
url=release['url'],
321-
revision=revision
324+
revision=revision,
322325
)
323326
return_code, output = cmd(command, verbose != 0)
324327
if return_code != 0:
@@ -342,6 +345,43 @@ def process_wheel(wheel_cache_dir, wheel, sources, verbose, index=INDEX_URL,
342345
output=output
343346
))
344347

348+
elif repo_type == 'hg':
349+
revision = ''
350+
if release['url'].startswith('hg+'):
351+
release['url'] = release['url'][3:]
352+
if '@' in release['url']:
353+
release['url'], revision = release['url'].split('@')
354+
355+
release['fetch_type'] = 'fetchhg'
356+
command = 'nix-prefetch-hg {url} {revision}'.format(
357+
url=release['url'],
358+
revision=revision,
359+
)
360+
return_code, output = cmd(command, verbose != 0)
361+
if return_code != 0:
362+
raise click.ClickException("URL {url} for package {name} is not valid.".format(
363+
url=release['url'],
364+
name=wheel['name']
365+
))
366+
HASH_PREFIX = 'hash is '
367+
REV_PREFIX = 'hg revision is '
368+
for output_line in output.split('\n'):
369+
print(output_line)
370+
output_line = output_line.strip()
371+
if output_line.startswith(HASH_PREFIX):
372+
release['hash_value'] = output_line[len(HASH_PREFIX):].strip()
373+
elif output_line.startswith(REV_PREFIX):
374+
release['rev'] = output_line[len(REV_PREFIX):].strip()
375+
376+
if release.get('hash_value', None) is None:
377+
raise click.ClickException('Could not determine the hash from ouput:\n{output}'.format(
378+
output=output
379+
))
380+
if release.get('rev', None) is None:
381+
raise click.ClickException('Could not determine the revision from ouput:\n{output}'.format(
382+
output=output
383+
))
384+
345385
else:
346386
url = "{}/{}/json".format(index, wheel['name'])
347387
r = requests.get(url, timeout=None)
@@ -366,6 +406,7 @@ def main(verbose, wheels, requirements_files, wheel_cache_dir, index=INDEX_URL):
366406

367407
# get url's from requirements_files
368408
sources = dict()
409+
repo_types = dict()
369410
for requirements_file in requirements_files:
370411
with open(requirements_file) as f:
371412
lines = f.readlines()
@@ -374,11 +415,15 @@ def main(verbose, wheels, requirements_files, wheel_cache_dir, index=INDEX_URL):
374415
if line.startswith('-e '):
375416
line = line[3:]
376417
if line.startswith('http://') or line.startswith('https://') or \
377-
line.startswith('git+'):
418+
line.startswith('git+') or line.startswith('hg+'):
378419
try:
379420
url, egg = line.split('#')
380421
name = egg.split('egg=')[1]
381-
sources[name] = url
422+
sources[name] = url.replace('-e git+','').replace('-e hg+','')
423+
if line.startswith('git+'):
424+
repo_types[name] = 'git'
425+
elif line.startswith('hg+'):
426+
repo_types[name] = 'hg'
382427
except:
383428
raise click.ClickException(
384429
"Requirement starting with http:// or https:// "
@@ -416,7 +461,8 @@ def main(verbose, wheels, requirements_files, wheel_cache_dir, index=INDEX_URL):
416461
click.echo("--------------------------------------------------------------------------")
417462

418463
metadata.append(
419-
process_wheel(wheel_cache_dir, wheel_metadata, sources, verbose, index))
464+
process_wheel(wheel_cache_dir, wheel_metadata, sources,
465+
repo_types, verbose, index))
420466
except Exception as e:
421467
if verbose == 0:
422468
click.echo(output)

src/pypi2nix/stage3.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ def main(packages_metadata,
152152
hash_value=item['hash_value'],
153153
rev=item['rev']
154154
)
155+
elif fetch_type == 'fetchhg':
156+
fetch_expression = 'pkgs.fetchhg { url = "%(url)s"; %(hash_type)s = "%(hash_value)s"; rev = "%(rev)s"; }' % dict(
157+
url=item['url'],
158+
hash_type=item['hash_type'],
159+
hash_value=item['hash_value'],
160+
rev=item['rev']
161+
)
155162
else:
156163
fetch_expression='pkgs.fetchurl { url = "%(url)s"; %(hash_type)s = "%(hash_value)s"; }' % dict(
157164
url=item['url'],

src/pypi2nix/utils.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ def cmd(command, verbose=False):
4141
if isinstance(command, str):
4242
command = shlex.split(command)
4343

44-
output = '|-> ' + ' '.join(command)
4544
if verbose:
4645
click.echo('|-> ' + ' '.join(command))
4746

@@ -57,12 +56,11 @@ def cmd(command, verbose=False):
5756
if line == '' and p.poll() is not None:
5857
break
5958
if line != '':
60-
output += ' ' + line
6159
if verbose:
6260
click.echo(' ' + line.rstrip('\n'))
6361
out.append(line)
6462

65-
return p.returncode, output
63+
return p.returncode, '\n'.join(out)
6664

6765

6866
def create_command_options(options):

0 commit comments

Comments
 (0)