- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / chromedriver / third_party / googlecode / googlecode_upload.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2006, 2007 Google Inc. All Rights Reserved.
4 # Author: danderson@google.com (David Anderson)
5 #
6 # Script for uploading files to a Google Code project.
7 #
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.
11 #
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.
20 #
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).
30 #
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.
38 #
39 # Licensed under the terms of the Apache Software License 2.0:
40 #  http://www.apache.org/licenses/LICENSE-2.0
41 #
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
45 #
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
49 #
50 #      http://www.apache.org/licenses/LICENSE-2.0
51
52 """Google Code file uploader script.
53 """
54
55 __author__ = 'danderson@google.com (David Anderson)'
56
57 import httplib
58 import os.path
59 import optparse
60 import getpass
61 import base64
62 import sys
63
64
65 def upload(file, project_name, user_name, password, summary, labels=None):
66   """Upload a file to a Google Code project's file server.
67
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.
76
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')]
88
89   form_fields = [('summary', summary)]
90   if labels is not None:
91     form_fields.extend([('label', l.strip()) for l in labels])
92
93   content_type, body = encode_upload_request(form_fields, file)
94
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,
102     }
103
104   server = httplib.HTTPSConnection(upload_host)
105   server.request('POST', upload_uri, body, headers)
106   resp = server.getresponse()
107   server.close()
108
109   if resp.status == 201:
110     location = resp.getheader('Location', None)
111   else:
112     location = None
113   return resp.status, resp.reason, location
114
115
116 def encode_upload_request(fields, file_path):
117   """Encode the given fields and file into a multipart form body.
118
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.
122
123   Returns: (content_type, body) ready for httplib.HTTP instance
124   """
125   BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla'
126   CRLF = '\r\n'
127
128   body = []
129
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,
135        '',
136        value,
137        ])
138
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()
144
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',
151      '',
152      file_content,
153      ])
154
155   # Finalize the form body
156   body.extend(['--' + BOUNDARY + '--', ''])
157
158   return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body)
159
160
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.
164
165   file_path, project_name, summary, and labels are passed as-is to upload.
166
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.
175   """
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]
186
187   if user_name is None or password is None:
188     raise RuntimeError('Missing user credentials for upload')
189
190   return upload(file_path, project_name, user_name, password, summary, labels)
191
192
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')
207
208   options, args = parser.parse_args()
209
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.')
218
219   file_path = args[0]
220
221   if options.labels:
222     labels = options.labels.split(',')
223   else:
224     labels = None
225
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
237
238
239 if __name__ == '__main__':
240   sys.exit(main())