summaryrefslogtreecommitdiff
path: root/linaro-cp.py
blob: 0e23bd648ec3619f24e03f4a8c9856bdd423289d (plain)
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
#!/usr/bin/env python

import argparse
import cStringIO
import os
import pycurl
import sys
import time

# Public artifacts BUILD-INFO.txt
build_info = 'Format-Version: 0.5\n\nFiles-Pattern: *\nLicense-Type: open\n'


def _get_transfer_queue(server_base, src, dst):
    transfer_queue = {}
    src_dir = os.path.abspath(src)
    for root, dirs, files in os.walk(src_dir):
        for f in files:
            src_file = os.path.join(root, f)
            dst_file = os.path.join(root, f)[len(src_dir):]
            dst_file = '%s%s%s' % (server_base, dst, dst_file)
            build_info_file = dst_file.replace(f, 'BUILD-INFO.txt')
            transfer_queue[dst_file] = src_file
            transfer_queue[build_info_file] = 'BUILD-INFO.txt'
    return transfer_queue


def _upload(curl, key, url, filename, retry_count=3):
    response = cStringIO.StringIO()
    send = [
        ('file', (pycurl.FORM_FILE, filename)),
        ('key', (pycurl.FORM_CONTENTS, key)),
    ]
    curl.setopt(pycurl.URL, url)
    curl.setopt(pycurl.HTTPPOST, send)
    curl.setopt(pycurl.WRITEFUNCTION, response.write)
    try:
        curl.perform()
    except Exception as e:
        if retry_count > 0:
            # server could be reloading or something. give it a second and
            # try again
            print('Upload failed for %s, retrying in 2 seconds' % url)
            time.sleep(2)
            return _upload(curl, key, url, filename, retry_count - 1)
        else:
            return str(e)

    return response.getvalue()


def _upload_transfer_queue(key, transfer_queue):
    curl = pycurl.Curl()
    transfer_failures = []
    for transfer_item in transfer_queue:
        http_status = _upload(
            curl, key, transfer_item, transfer_queue[transfer_item])
        if http_status != 'OK':
            transfer_failures.append('%s: %s' % (transfer_item, http_status))
    curl.close()
    return transfer_failures


def main():
    parser = argparse.ArgumentParser(
        description='Copy file(s) from source to destination')
    parser.add_argument('-k', '--key', help='key used for the copy')
    parser.add_argument('--server', default='http://snapshots.linaro.org/',
                        help='Publishing API server. default=%(default)s')
    parser.add_argument('src', help='source file(s) to copy')
    parser.add_argument('dst', help='destination to copy the file(s)')

    arguments = parser.parse_args()
    src = arguments.src
    dst = arguments.dst
    # Publish key is required. Fallback to PUBLISH_KEY environment
    # variable when it isn't passed as an argument
    if arguments.key:
        key = arguments.key
    else:
        key = os.environ.get('PUBLISH_KEY')
        if key is None:
            sys.exit('Key is not defined.')

    # Write BUILD-INFO.txt file on the filesystem
    # A better solution is available in PycURL HEAD,
    # using FORM_BUFFER/FORM_BUFFERPTR
    with open('BUILD-INFO.txt', 'w') as f:
        f.write(build_info)

    transfer_queue = _get_transfer_queue(arguments.server, src, dst)
    transfer_failures = _upload_transfer_queue(key, transfer_queue)

    # Remove temporary BUILD-INFO.txt file
    os.remove('BUILD-INFO.txt')

    if len(transfer_failures) > 0:
        sys.exit('Failed to transfer:\n  %s' % '\n  '.join(transfer_failures))


if __name__ == '__main__':
    main()