blob: f8dccdc50b9a26000b2351b30cf2258880b78b57 [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#
2# Copyright (C) 2008 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import getpass
17import os
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070018import sys
19from tempfile import mkstemp
20
21from codereview.proto_client import HttpRpc, Proxy
22from codereview.review_pb2 import ReviewService_Stub
23from codereview.upload_bundle_pb2 import *
24from git_command import GitCommand
25from error import UploadError
26
27try:
28 import readline
29except ImportError:
30 pass
31
32MAX_SEGMENT_SIZE = 1020 * 1024
33
34def _GetRpcServer(email, server, save_cookies):
35 """Returns an RpcServer.
36
37 Returns:
38 A new RpcServer, on which RPC calls can be made.
39 """
40
41 def GetUserCredentials():
42 """Prompts the user for a username and password."""
43 e = email
44 if e is None:
45 e = raw_input("Email: ").strip()
46 password = getpass.getpass("Password for %s: " % e)
47 return (e, password)
48
49 # If this is the dev_appserver, use fake authentication.
50 lc_server = server.lower()
51 if lc_server == "localhost" or lc_server.startswith("localhost:"):
52 if email is None:
53 email = "test@example.com"
54 server = HttpRpc(
55 server,
56 lambda: (email, "password"),
57 extra_headers={"Cookie":
58 'dev_appserver_login="%s:False"' % email})
59 # Don't try to talk to ClientLogin.
60 server.authenticated = True
61 return server
62
63 if save_cookies:
64 cookie_file = ".gerrit_cookies"
65 else:
66 cookie_file = None
67
68 return HttpRpc(server, GetUserCredentials,
69 cookie_file=cookie_file)
70
71def UploadBundle(project,
72 server,
73 email,
74 dest_project,
75 dest_branch,
76 src_branch,
77 bases,
78 save_cookies=True):
79
80 srv = _GetRpcServer(email, server, save_cookies)
81 review = Proxy(ReviewService_Stub(srv))
82 tmp_fd, tmp_bundle = mkstemp(".bundle", ".gpq")
83 os.close(tmp_fd)
84
85 srcid = project.bare_git.rev_parse(src_branch)
86 revlist = project._revlist(src_branch, *bases)
87
88 if srcid not in revlist:
89 # This can happen if src_branch is an annotated tag
90 #
91 revlist.append(srcid)
92 revlist_size = len(revlist) * 42
93
94 try:
95 cmd = ['bundle', 'create', tmp_bundle, src_branch]
96 cmd.extend(bases)
97 if GitCommand(project, cmd).Wait() != 0:
98 raise UploadError('cannot create bundle')
99 fd = open(tmp_bundle, "rb")
100
101 bundle_id = None
102 segment_id = 0
103 next_data = fd.read(MAX_SEGMENT_SIZE - revlist_size)
104
105 while True:
106 this_data = next_data
107 next_data = fd.read(MAX_SEGMENT_SIZE)
108 segment_id += 1
109
110 if bundle_id is None:
111 req = UploadBundleRequest()
112 req.dest_project = str(dest_project)
113 req.dest_branch = str(dest_branch)
114 for c in revlist:
115 req.contained_object.append(c)
116 else:
117 req = UploadBundleContinue()
118 req.bundle_id = bundle_id
119 req.segment_id = segment_id
120
121 req.bundle_data = this_data
122 if len(next_data) > 0:
123 req.partial_upload = True
124 else:
125 req.partial_upload = False
126
127 if bundle_id is None:
128 rsp = review.UploadBundle(req)
129 else:
130 rsp = review.ContinueBundle(req)
131
132 if rsp.status_code == UploadBundleResponse.CONTINUE:
133 bundle_id = rsp.bundle_id
134 elif rsp.status_code == UploadBundleResponse.RECEIVED:
135 bundle_id = rsp.bundle_id
136 return bundle_id
137 else:
138 if rsp.status_code == UploadBundleResponse.UNKNOWN_PROJECT:
139 reason = 'unknown project "%s"' % dest_project
140 elif rsp.status_code == UploadBundleResponse.UNKNOWN_BRANCH:
141 reason = 'unknown branch "%s"' % dest_branch
142 elif rsp.status_code == UploadBundleResponse.UNKNOWN_BUNDLE:
143 reason = 'unknown bundle'
144 elif rsp.status_code == UploadBundleResponse.NOT_BUNDLE_OWNER:
145 reason = 'not bundle owner'
146 elif rsp.status_code == UploadBundleResponse.BUNDLE_CLOSED:
147 reason = 'bundle closed'
148 elif rsp.status_code == UploadBundleResponse.UNAUTHORIZED_USER:
149 reason = ('Unauthorized user. Visit http://%s/hello to sign up.'
150 % server)
151 else:
152 reason = 'unknown error ' + str(rsp.status_code)
153 raise UploadError(reason)
154 finally:
155 os.unlink(tmp_bundle)