Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / test / chromedriver / third_party / googlecode / googlecode_upload.py
blobdec4eed2a8d7054fe9bf9557194e639cf17f18bc
1 #!/usr/bin/env python
3 # Copyright 2006, 2007 Google Inc. All Rights Reserved.
4 # Author: danderson@google.com (David Anderson)
6 # Script for uploading files to a Google Code project.
8 # This is intended to be both a useful script for people who want to
9 # streamline project uploads and a reference implementation for
10 # uploading files to Google Code projects.
12 # To upload a file to Google Code, you need to provide a path to the
13 # file on your local machine, a small summary of what the file is, a
14 # project name, and a valid account that is a member or owner of that
15 # project. You can optionally provide a list of labels that apply to
16 # the file. The file will be uploaded under the same name that it has
17 # in your local filesystem (that is, the "basename" or last path
18 # component). Run the script with '--help' to get the exact syntax
19 # and available options.
21 # Note that the upload script requests that you enter your
22 # googlecode.com password. This is NOT your Gmail account password!
23 # This is the password you use on googlecode.com for committing to
24 # Subversion and uploading files. You can find your password by going
25 # to http://code.google.com/hosting/settings when logged in with your
26 # Gmail account. If you have already committed to your project's
27 # Subversion repository, the script will automatically retrieve your
28 # credentials from there (unless disabled, see the output of '--help'
29 # for details).
31 # If you are looking at this script as a reference for implementing
32 # your own Google Code file uploader, then you should take a look at
33 # the upload() function, which is the meat of the uploader. You
34 # basically need to build a multipart/form-data POST request with the
35 # right fields and send it to https://PROJECT.googlecode.com/files .
36 # Authenticate the request using HTTP Basic authentication, as is
37 # shown below.
39 # Licensed under the terms of the Apache Software License 2.0:
40 # http://www.apache.org/licenses/LICENSE-2.0
42 # Questions, comments, feature requests and patches are most welcome.
43 # Please direct all of these to the Google Code users group:
44 # http://groups.google.com/group/google-code-hosting
46 # Licensed under the Apache License, Version 2.0 (the "License");
47 # you may not use this file except in compliance with the License.
48 # You may obtain a copy of the License at
50 # http://www.apache.org/licenses/LICENSE-2.0
52 """Google Code file uploader script.
53 """
55 __author__ = 'danderson@google.com (David Anderson)'
57 import httplib
58 import os.path
59 import optparse
60 import getpass
61 import base64
62 import sys
65 def upload(file, project_name, user_name, password, summary, labels=None):
66 """Upload a file to a Google Code project's file server.
68 Args:
69 file: The local path to the file.
70 project_name: The name of your project on Google Code.
71 user_name: Your Google account name.
72 password: The googlecode.com password for your account.
73 Note that this is NOT your global Google Account password!
74 summary: A small description for the file.
75 labels: an optional list of label strings with which to tag the file.
77 Returns: a tuple:
78 http_status: 201 if the upload succeeded, something else if an
79 error occured.
80 http_reason: The human-readable string associated with http_status
81 file_url: If the upload succeeded, the URL of the file on Google
82 Code, None otherwise.
83 """
84 # The login is the user part of user@gmail.com. If the login provided
85 # is in the full user@domain form, strip it down.
86 if user_name.endswith('@gmail.com'):
87 user_name = user_name[:user_name.index('@gmail.com')]
89 form_fields = [('summary', summary)]
90 if labels is not None:
91 form_fields.extend([('label', l.strip()) for l in labels])
93 content_type, body = encode_upload_request(form_fields, file)
95 upload_host = '%s.googlecode.com' % project_name
96 upload_uri = '/files'
97 auth_token = base64.b64encode('%s:%s'% (user_name, password))
98 headers = {
99 'Authorization': 'Basic %s' % auth_token,
100 'User-Agent': 'Googlecode.com uploader v0.9.4',
101 'Content-Type': content_type,
104 server = httplib.HTTPSConnection(upload_host)
105 server.request('POST', upload_uri, body, headers)
106 resp = server.getresponse()
107 server.close()
109 if resp.status == 201:
110 location = resp.getheader('Location', None)
111 else:
112 location = None
113 return resp.status, resp.reason, location
116 def encode_upload_request(fields, file_path):
117 """Encode the given fields and file into a multipart form body.
119 fields is a sequence of (name, value) pairs. file is the path of
120 the file to upload. The file will be uploaded to Google Code with
121 the same file name.
123 Returns: (content_type, body) ready for httplib.HTTP instance
125 BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla'
126 CRLF = '\r\n'
128 body = []
130 # Add the metadata about the upload first
131 for key, value in fields:
132 body.extend(
133 ['--' + BOUNDARY,
134 'Content-Disposition: form-data; name="%s"' % key,
136 value,
139 # Now add the file itself
140 file_name = os.path.basename(file_path)
141 f = open(file_path, 'rb')
142 file_content = f.read()
143 f.close()
145 body.extend(
146 ['--' + BOUNDARY,
147 'Content-Disposition: form-data; name="filename"; filename="%s"'
148 % file_name,
149 # The upload server determines the mime-type, no need to set it.
150 'Content-Type: application/octet-stream',
152 file_content,
155 # Finalize the form body
156 body.extend(['--' + BOUNDARY + '--', ''])
158 return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body)
161 def upload_find_auth(file_path, project_name, summary, labels=None,
162 user_name=None, password=None, tries=3):
163 """Find credentials and upload a file to a Google Code project's file server.
165 file_path, project_name, summary, and labels are passed as-is to upload.
167 Args:
168 file_path: The local path to the file.
169 project_name: The name of your project on Google Code.
170 summary: A small description for the file.
171 labels: an optional list of label strings with which to tag the file.
172 config_dir: Path to Subversion configuration directory, 'none', or None.
173 user_name: Your Google account name.
174 tries: How many attempts to make.
176 if user_name is None or password is None:
177 from netrc import netrc
178 # Chromium edit: Works on windows without requiring HOME to be set.
179 netrc_path = os.path.join(os.path.expanduser('~'), '.netrc')
180 authenticators = netrc(netrc_path).authenticators("code.google.com")
181 if authenticators:
182 if user_name is None:
183 user_name = authenticators[0]
184 if password is None:
185 password = authenticators[2]
187 if user_name is None or password is None:
188 raise RuntimeError('Missing user credentials for upload')
190 return upload(file_path, project_name, user_name, password, summary, labels)
193 def main():
194 parser = optparse.OptionParser(usage='googlecode-upload.py -s SUMMARY '
195 '-p PROJECT [options] FILE')
196 parser.add_option('-s', '--summary', dest='summary',
197 help='Short description of the file')
198 parser.add_option('-p', '--project', dest='project',
199 help='Google Code project name')
200 parser.add_option('-u', '--user', dest='user',
201 help='Your Google Code username')
202 parser.add_option('-w', '--password', dest='password',
203 help='Your Google Code password')
204 parser.add_option('-l', '--labels', dest='labels',
205 help='An optional list of comma-separated labels to attach '
206 'to the file')
208 options, args = parser.parse_args()
210 if not options.summary:
211 parser.error('File summary is missing.')
212 elif not options.project:
213 parser.error('Project name is missing.')
214 elif len(args) < 1:
215 parser.error('File to upload not provided.')
216 elif len(args) > 1:
217 parser.error('Only one file may be specified.')
219 file_path = args[0]
221 if options.labels:
222 labels = options.labels.split(',')
223 else:
224 labels = None
226 status, reason, url = upload_find_auth(file_path, options.project,
227 options.summary, labels,
228 options.user, options.password)
229 if url:
230 print 'The file was uploaded successfully.'
231 print 'URL: %s' % url
232 return 0
233 else:
234 print 'An error occurred. Your file was not uploaded.'
235 print 'Google Code upload server said: %s (%s)' % (reason, status)
236 return 1
239 if __name__ == '__main__':
240 sys.exit(main())