blob: a49fb2325235d42810847e1995db9d451ffd822d [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
18import subprocess
19import sys
20from tempfile import mkstemp
21
22from codereview.proto_client import HttpRpc, Proxy
23from codereview.review_pb2 import ReviewService_Stub
24from codereview.upload_bundle_pb2 import *
25from git_command import GitCommand
26from error import UploadError
27
28try:
29 import readline
30except ImportError:
31 pass
32
33MAX_SEGMENT_SIZE = 1020 * 1024
34
35def _GetRpcServer(email, server, save_cookies):
36 """Returns an RpcServer.
37
38 Returns:
39 A new RpcServer, on which RPC calls can be made.
40 """
41
42 def GetUserCredentials():
43 """Prompts the user for a username and password."""
44 e = email
45 if e is None:
46 e = raw_input("Email: ").strip()
47 password = getpass.getpass("Password for %s: " % e)
48 return (e, password)
49
50 # If this is the dev_appserver, use fake authentication.
51 lc_server = server.lower()
52 if lc_server == "localhost" or lc_server.startswith("localhost:"):
53 if email is None:
54 email = "test@example.com"
55 server = HttpRpc(
56 server,
57 lambda: (email, "password"),
58 extra_headers={"Cookie":
59 'dev_appserver_login="%s:False"' % email})
60 # Don't try to talk to ClientLogin.
61 server.authenticated = True
62 return server
63
64 if save_cookies:
65 cookie_file = ".gerrit_cookies"
66 else:
67 cookie_file = None
68
69 return HttpRpc(server, GetUserCredentials,
70 cookie_file=cookie_file)
71
72def UploadBundle(project,
73 server,
74 email,
75 dest_project,
76 dest_branch,
77 src_branch,
78 bases,
79 save_cookies=True):
80
81 srv = _GetRpcServer(email, server, save_cookies)
82 review = Proxy(ReviewService_Stub(srv))
83 tmp_fd, tmp_bundle = mkstemp(".bundle", ".gpq")
84 os.close(tmp_fd)
85
86 srcid = project.bare_git.rev_parse(src_branch)
87 revlist = project._revlist(src_branch, *bases)
88
89 if srcid not in revlist:
90 # This can happen if src_branch is an annotated tag
91 #
92 revlist.append(srcid)
93 revlist_size = len(revlist) * 42
94
95 try:
96 cmd = ['bundle', 'create', tmp_bundle, src_branch]
97 cmd.extend(bases)
98 if GitCommand(project, cmd).Wait() != 0:
99 raise UploadError('cannot create bundle')
100 fd = open(tmp_bundle, "rb")
101
102 bundle_id = None
103 segment_id = 0
104 next_data = fd.read(MAX_SEGMENT_SIZE - revlist_size)
105
106 while True:
107 this_data = next_data
108 next_data = fd.read(MAX_SEGMENT_SIZE)
109 segment_id += 1
110
111 if bundle_id is None:
112 req = UploadBundleRequest()
113 req.dest_project = str(dest_project)
114 req.dest_branch = str(dest_branch)
115 for c in revlist:
116 req.contained_object.append(c)
117 else:
118 req = UploadBundleContinue()
119 req.bundle_id = bundle_id
120 req.segment_id = segment_id
121
122 req.bundle_data = this_data
123 if len(next_data) > 0:
124 req.partial_upload = True
125 else:
126 req.partial_upload = False
127
128 if bundle_id is None:
129 rsp = review.UploadBundle(req)
130 else:
131 rsp = review.ContinueBundle(req)
132
133 if rsp.status_code == UploadBundleResponse.CONTINUE:
134 bundle_id = rsp.bundle_id
135 elif rsp.status_code == UploadBundleResponse.RECEIVED:
136 bundle_id = rsp.bundle_id
137 return bundle_id
138 else:
139 if rsp.status_code == UploadBundleResponse.UNKNOWN_PROJECT:
140 reason = 'unknown project "%s"' % dest_project
141 elif rsp.status_code == UploadBundleResponse.UNKNOWN_BRANCH:
142 reason = 'unknown branch "%s"' % dest_branch
143 elif rsp.status_code == UploadBundleResponse.UNKNOWN_BUNDLE:
144 reason = 'unknown bundle'
145 elif rsp.status_code == UploadBundleResponse.NOT_BUNDLE_OWNER:
146 reason = 'not bundle owner'
147 elif rsp.status_code == UploadBundleResponse.BUNDLE_CLOSED:
148 reason = 'bundle closed'
149 elif rsp.status_code == UploadBundleResponse.UNAUTHORIZED_USER:
150 reason = ('Unauthorized user. Visit http://%s/hello to sign up.'
151 % server)
152 else:
153 reason = 'unknown error ' + str(rsp.status_code)
154 raise UploadError(reason)
155 finally:
156 os.unlink(tmp_bundle)