~ubuntu-branches/debian/sid/simpleitk/sid

« back to all changes in this revision

Viewing changes to Utilities/UploadBinaryData.py

  • Committer: Package Import Robot
  • Author(s): Ghislain Antony Vaillant
  • Date: 2017-11-02 08:49:18 UTC
  • Revision ID: package-import@ubuntu.com-20171102084918-7hs09ih668xq87ej
Tags: upstream-1.0.1
ImportĀ upstreamĀ versionĀ 1.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
from __future__ import print_function
 
4
 
 
5
description = """
 
6
Upload binary data to Midas.
 
7
 
 
8
Since every local Git repository contains a copy of the entire project history,
 
9
it is important to avoid adding large binary files directly to the repository.
 
10
Large binary files added and removed through the history of a project will cause
 
11
the repository to become bloated, take up too much disk space, require excessive
 
12
time and bandwidth to download, etc.
 
13
 
 
14
The solution to this problem adopted by this project is to store binary files,
 
15
such as images, in a separate location outside the repository, then download the
 
16
files at build time with CMake.
 
17
 
 
18
A "content link" file containing an identifying MD5 checksum is stored in the
 
19
Git repository at the path where the file would exist with the ".md5" extension
 
20
added to the file.  CMake will find these content link files at build time,
 
21
download them from a list of server resources, and create symlinks or copies of
 
22
the original files at the corresponding location in the build tree.
 
23
 
 
24
The Midas server at
 
25
 
 
26
  https://midas3.kitware.com/midas/
 
27
 
 
28
is an ITK community resource where any community member can upload binary data
 
29
files.  This script automates the upload of data to the server and generation of
 
30
the content link file.  Before using this script, please go to the Midas
 
31
website, register, and join the ITK community.
 
32
 
 
33
This script requires the Python module pydas:
 
34
 
 
35
    https://github.com/midasplatform/pydas
 
36
 
 
37
which can be installed with::
 
38
 
 
39
  pip install pydas
 
40
 
 
41
Pass in the input binary files to be uploaded. These should be files
 
42
located in the SimpleITK source tree. They will be uploaded and
 
43
replaced with a *.md5 file that can be added to the current
 
44
commit with "git add -- path/to/file.md5".
 
45
"""
 
46
 
 
47
import optparse
 
48
import hashlib
 
49
import os
 
50
import subprocess
 
51
import sys
 
52
import pydas
 
53
 
 
54
 
 
55
def connect_to_midas(email=None, api_key=None):
 
56
    midas_url = 'https://midas3.kitware.com/midas/'
 
57
    #pydas.login(url=midas_url, email=email, api_key=api_key)
 
58
    try:
 
59
        pydas.login(url=midas_url, email=email, api_key=api_key)
 
60
    except:
 
61
        print('Error occurred while logging in to ' + midas_url)
 
62
        sys.exit(1)
 
63
    session = pydas.session
 
64
    communicator = session.communicator
 
65
    return session, communicator
 
66
 
 
67
 
 
68
def upload_to_midas(input_file, output_file, folders, session, communicator):
 
69
    # get the MD5 checksum
 
70
    print('Computing MD5 checksum...')
 
71
    md5 = hashlib.md5()
 
72
    with open(input_file, 'rb') as fp:
 
73
        for chunk in iter(lambda: fp.read(128 * md5.block_size), b''):
 
74
            md5.update(chunk)
 
75
    md5hash = md5.hexdigest()
 
76
    print('Checksum: ' + md5hash)
 
77
 
 
78
    # upload to Midas
 
79
    def get_child_folder(parent, child_name):
 
80
        children = communicator.folder_children(session.token,
 
81
                                                parent['folder_id'])
 
82
        for folder in children['folders']:
 
83
            if folder['name'] == child_name:
 
84
                return folder
 
85
        return None
 
86
    itk_community = communicator.get_community_by_name('ITK')
 
87
    itk_public = get_child_folder(itk_community, 'Public')
 
88
    simpleitk = get_child_folder(itk_public, 'SimpleITK')
 
89
 
 
90
    current_folder = simpleitk
 
91
    for folder in folders:
 
92
        child_folder = get_child_folder(current_folder, folder)
 
93
        if child_folder is None:
 
94
            print('Creating folder: ' + folder)
 
95
            current_folder = \
 
96
                communicator.create_folder(session.token,
 
97
                                           folder,
 
98
                                           current_folder['folder_id'])
 
99
        else:
 
100
            current_folder = child_folder
 
101
 
 
102
    # get the existing or create a new item to hold the file
 
103
    item_name = os.path.basename(input_file)
 
104
    item_id = None
 
105
    current_folder_children = \
 
106
        communicator.folder_children(session.token,
 
107
                                     current_folder['folder_id'])
 
108
    if 'items' in current_folder_children:
 
109
        for item in current_folder_children['items']:
 
110
            if item['name'] == item_name:
 
111
                item_id = item['item_id']
 
112
                break
 
113
 
 
114
    if item_id is None:
 
115
        new_item = communicator.create_item(session.token, item_name,
 
116
                                            current_folder['folder_id'])
 
117
        item_id = new_item['item_id']
 
118
 
 
119
    upload_token = communicator.generate_upload_token(session.token,
 
120
                                                      item_id,
 
121
                                                      item_name,
 
122
                                                      md5hash)
 
123
    if upload_token != "":
 
124
        communicator.perform_upload(upload_token,
 
125
                                    item_name,
 
126
                                    item_id=item_id,
 
127
                                    revision='head',
 
128
                                    filepath=input_file)
 
129
 
 
130
    # write the content link file
 
131
    with open(output_file, 'w') as fp:
 
132
        fp.write(md5hash)
 
133
        fp.write('\n')
 
134
 
 
135
 
 
136
def find_git_dir(filepath):
 
137
    """Find our best estimate of GIT_DIR to locate the root of the SimpleITK
 
138
    repository."""
 
139
    filepath = os.path.abspath(filepath)
 
140
    head, tail = os.path.split(filepath)
 
141
    previous_head = ''
 
142
    while head != previous_head:
 
143
        if os.path.exists(os.path.join(head, '.git')):
 
144
            return head
 
145
        previous_head = head
 
146
        head, tail = os.path.split(head)
 
147
    print('Could not find the root of the SimpleITK repository!')
 
148
    sys.exit(1)
 
149
 
 
150
 
 
151
def run(input_files, output_files,
 
152
        email=None, api_key=None,
 
153
        no_delete=False):
 
154
    git_dir = find_git_dir(input_files[0])
 
155
 
 
156
    git_email_cmd = subprocess.Popen(['git', 'config', 'user.email'],
 
157
                                     cwd=git_dir,
 
158
                                     stdout=subprocess.PIPE)
 
159
    if git_email_cmd.wait() is 0:
 
160
        git_email = git_email_cmd.stdout.readline().strip()
 
161
        email_input = raw_input('Email [' + git_email + ']: ')
 
162
        if email_input == '':
 
163
            email = git_email
 
164
        else:
 
165
            email = email_input
 
166
 
 
167
    session, communicator = connect_to_midas(email, api_key)
 
168
 
 
169
    for ii in range(len(input_files)):
 
170
        input_abspath = os.path.abspath(input_files[ii])
 
171
        folders = input_abspath[len(git_dir)+1:].split(os.path.sep)[:-1]
 
172
        upload_to_midas(input_files[ii], output_files[ii], folders,
 
173
                        session, communicator)
 
174
 
 
175
        if not no_delete:
 
176
            os.remove(input_files[ii])
 
177
 
 
178
 
 
179
if __name__ == '__main__':
 
180
    usage = "%prog [options] input1 input2 ... inputN"
 
181
    parser = optparse.OptionParser(usage=usage)
 
182
    parser.add_option('--api-key-file', '-k', dest='api_key_file',
 
183
            help="A file that contains your Midas user's API key.")
 
184
    parser.add_option('--email', '-e',
 
185
            help="Email address associated with your Midas account.")
 
186
    parser.add_option('--no-delete', '-n', action='store_true',
 
187
            dest='no_delete',
 
188
            help='Do not remove the input files after upload.')
 
189
    (options, input_files) = parser.parse_args()
 
190
 
 
191
    if options.api_key_file:
 
192
        with open(options.api_key_file, 'r') as fp:
 
193
            api_key = fp.readline()
 
194
        api_key = api_key.strip()
 
195
    else:
 
196
        api_key = None
 
197
 
 
198
    output_files = []
 
199
    for ii in range(len(input_files)):
 
200
        output_files.append(input_files[ii] + '.md5')
 
201
 
 
202
    no_delete = options.no_delete
 
203
 
 
204
    run(input_files, output_files,
 
205
        email=options.email, api_key=api_key,
 
206
        no_delete=no_delete)