/
upload_or_check_non_existence
executable file
·119 lines (94 loc) · 4.06 KB
/
upload_or_check_non_existence
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python
from __future__ import print_function
import argparse
import contextlib
import hashlib
import os
import shutil
import subprocess
import sys
import tempfile
from binstar_client.utils import get_server_api
import binstar_client.errors
from conda_build.api import get_output_file_paths, render
@contextlib.contextmanager
def get_temp_token(token):
dn = tempfile.mkdtemp()
fn = os.path.join(dn, "binstar.token")
with open(fn, "w") as fh:
fh.write(token)
yield fn
shutil.rmtree(dn)
def built_distribution_already_exists(cli, meta, fname, owner):
"""
Checks to see whether the built recipe (aka distribution) already
exists on the owner/user's binstar account.
"""
folder, basename = os.path.split(fname)
_, platform = os.path.split(folder)
distro_name = '{}/{}'.format(platform, basename)
try:
dist_info = cli.distribution(owner, meta.name(), meta.version(),
distro_name)
except binstar_client.errors.NotFound:
dist_info = {}
exists = bool(dist_info)
return exists
def upload(token_fn, fname, owner, channels):
subprocess.check_call(['anaconda', '-t', token_fn,
'upload', fname,
'--user={}'.format(owner),
'--channel={}'.format(channels)],
env=os.environ)
def main():
token = os.environ.get('BINSTAR_TOKEN')
description = ('Upload or check consistency of a built version of a '
'conda recipe with binstar. Note: The existence of the '
'BINSTAR_TOKEN environment variable determines '
'whether the upload should actually take place.')
parser = argparse.ArgumentParser(description=description)
parser.add_argument(
'-m', '--variant-config-files',
action="append",
help="""Additional variant config files to add. These yaml files can contain
keys such as `c_compiler` and `target_platform` to form a build matrix."""
)
parser.add_argument('recipe_dir', help='the conda recipe directory')
parser.add_argument('owner', help='the binstar owner/user')
parser.add_argument('--channel', help='the binstar channel', default='main')
args = parser.parse_args()
recipe_dir, owner, channel = args.recipe_dir, args.owner, args.channel
cli = get_server_api(token=token)
metas = render(
recipe_dir, variant_config_files=args.variant_config_files)
# Print the skipped distributions
skipped_distributions = [ m for m, _, _ in metas if m.skip() ]
for m in skipped_distributions:
print("{} configuration was skipped in build/skip.".format(m.name()))
# The list of built/not skipped distributions
built_distributions = [(m, path)
for m, _, _ in metas
for path in get_output_file_paths(m)
if not m.skip()]
# These are the ones that already exist on the owner channel's
existing_distributions = [path for m, path in built_distributions
if built_distribution_already_exists(cli, m, path, owner)]
for d in existing_distributions:
print('Distribution {} already exists for {}'.format(d, owner))
# These are the ones that are new to the owner channel's
new_distributions = [path for m, path in built_distributions
if not built_distribution_already_exists(cli, m, path, owner)]
# This is the actual fix where we create the token file once and reuse it for all uploads
if token:
with get_temp_token(cli.token) as token_fn:
for path in new_distributions:
upload(token_fn, path, owner, channel)
print('Uploaded {}'.format(path))
return True
else:
for path in new_distributions:
print("Distribution {} is new for {}, but no upload is taking place "
"because the BINSTAR_TOKEN is missing.".format(path, owner))
return False
if __name__ == '__main__':
main()