diff options
Diffstat (limited to 'webapp/codereview/review_service.py')
-rw-r--r-- | webapp/codereview/review_service.py | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/webapp/codereview/review_service.py b/webapp/codereview/review_service.py new file mode 100644 index 0000000000..58dca738ab --- /dev/null +++ b/webapp/codereview/review_service.py @@ -0,0 +1,125 @@ +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +from google.appengine.api import users +from google.appengine.ext import db + +from models import gql, Project, Branch, Account +import git_models + +from review_pb2 import * +from upload_bundle_pb2 import * +from internal.util import automatic_retry + +class ReviewServiceImp(ReviewService): + """ + Implements the review_service API for developer clients. + """ + + @automatic_retry + def UploadBundle(self, rpc_controller, req, done): + """ + Receives an uploaded Git style bundle and queues it for processing. + """ + rsp = UploadBundleResponse() + + # can't get here if there isn't a current user + current_user = users.get_current_user() + + if not Account.get_account_for_user(current_user).cla_verified: + rsp.status_code = UploadBundleResponse.UNAUTHORIZED_USER + done(rsp) + return + + if not req.dest_project: + rsp.status_code = UploadBundleResponse.UNKNOWN_PROJECT + done(rsp) + return + + proj = req.dest_project + if proj.endswith(".git"): + proj = proj[0 : len(proj) - 4] + + proj = Project.get_project_for_name(proj) + if not proj: + rsp.status_code = UploadBundleResponse.UNKNOWN_PROJECT + done(rsp) + return + + if not req.dest_branch: + rsp.status_code = UploadBundleResponse.UNKNOWN_BRANCH + done(rsp) + + brch = Branch.get_branch_for_name(proj, req.dest_branch) + if not brch: + rsp.status_code = UploadBundleResponse.UNKNOWN_BRANCH + done(rsp) + return + + rb = git_models.ReceivedBundle( + dest_project = proj, + dest_branch = brch, + owner = current_user, + state = git_models.ReceivedBundle.STATE_UPLOADING, + contained_objects = list(req.contained_object)) + rb.put() + + rsp.bundle_id = str(rb.key().id()) + self._store_segment(req, rsp, rb, 1) + done(rsp) + + @automatic_retry + def ContinueBundle(self, rpc_controller, req, done): + rsp = UploadBundleResponse() + rsp.bundle_id = req.bundle_id + + rb = git_models.ReceivedBundle.get_by_id(int(req.bundle_id)) + if rb is None: + rsp.status_code = UploadBundleResponse.UNKNOWN_BUNDLE + done(rsp) + return + + if rb.owner != users.get_current_user(): + rsp.status_code = UploadBundleResponse.NOT_BUNDLE_OWNER + done(rsp) + return + + self._store_segment(req, rsp, rb, req.segment_id) + done(rsp) + + def _store_segment(self, req, rsp, rb, segment_id): + rb.set_segment(segment_id, req.bundle_data) + def trans(): + b = db.get(rb.key()) + if b.state != git_models.ReceivedBundle.STATE_UPLOADING: + return False + + if b.n_segments < segment_id: + b.n_segments = segment_id + if not req.partial_upload: + b.state = git_models.ReceivedBundle.STATE_NEW + b.put() + return True + + if db.run_in_transaction(trans): + if req.partial_upload: + rsp.status_code = UploadBundleResponse.CONTINUE + else: + rb.ready() + rsp.status_code = UploadBundleResponse.RECEIVED + else: + rsp.status_code = UploadBundleResponse.BUNDLE_CLOSED + |