summaryrefslogtreecommitdiffstats
path: root/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/UnstageAction.java
blob: 22e74db0af8f728b0373691b77ca46212c4b82ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright (C) 2011 The Android Open Source Project
//
// 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.

package com.google.gerrit.httpd.rpc.topic;

import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.TopicDetail;
import com.google.gerrit.common.errors.NoSuchEntityException;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.Branch;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeSet;
import com.google.gerrit.reviewdb.ChangeSetElement;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.reviewdb.Topic;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.TopicUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeOp;
import com.google.gerrit.server.git.MergeQueue;
import com.google.gerrit.server.project.CanSubmitResult;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchRefException;
import com.google.gerrit.server.project.NoSuchTopicException;
import com.google.gerrit.server.project.TopicControl;
import com.google.gerrit.server.workflow.TopicFunctionState;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import org.eclipse.jgit.lib.Repository;

import java.io.IOException;
import java.util.List;


class UnstageAction extends Handler<TopicDetail> {
  interface Factory {
    UnstageAction create(ChangeSet.Id changeSetId);
  }

  private final ReviewDb db;
  private final MergeQueue merger;
  private final ApprovalTypes approvalTypes;
  private final IdentifiedUser user;
  private final TopicDetailFactory.Factory topicDetailFactory;
  private final ChangeControl.Factory changeControlFactory;
  private final TopicControl.Factory topicControlFactory;
  private final TopicFunctionState.Factory topicFunctionState;
  private final MergeOp.Factory opFactory;
  private final GitRepositoryManager gitManager;
  private final ChangeHookRunner hooks;

  private final ChangeSet.Id changeSetId;

  @Inject
  UnstageAction(final ReviewDb db, final MergeQueue mq,
      final IdentifiedUser user,
      final ApprovalTypes approvalTypes,
      final TopicDetailFactory.Factory topicDetailFactory,
      final ChangeControl.Factory changeControlFactory,
      final TopicControl.Factory topicControlFactory,
      final TopicFunctionState.Factory topicFunctionState,
      final MergeOp.Factory opFactory,
      final GitRepositoryManager gitManager,
      final ChangeHookRunner hooks,
      @Assisted final ChangeSet.Id changeSetId) {
    this.db = db;
    this.merger = mq;
    this.approvalTypes = approvalTypes;
    this.user = user;
    this.changeControlFactory = changeControlFactory;
    this.topicControlFactory = topicControlFactory;
    this.topicDetailFactory = topicDetailFactory;
    this.topicFunctionState = topicFunctionState;
    this.opFactory = opFactory;
    this.gitManager = gitManager;
    this.hooks = hooks;

    this.changeSetId = changeSetId;
  }

  @Override
  public TopicDetail call() throws OrmException, NoSuchEntityException,
      IllegalStateException, ChangeSetInfoNotAvailableException,
      NoSuchTopicException, NoSuchChangeException {

    final Topic.Id topicId = changeSetId.getParentKey();
    final TopicControl topicControl =
        topicControlFactory.validateFor(topicId);

    CanSubmitResult result = topicControl.canStage(db, changeSetId,
        changeControlFactory, approvalTypes, topicFunctionState);

    Repository git = null;
    if (result == CanSubmitResult.OK) {
      try {
        // Open a handle to Git repository.
        git =
          gitManager.openRepository(topicControl.getProject().getNameKey());

        // Set topic status to NEW
        TopicUtil.rejectStagedTopic(changeSetId, user, db, opFactory, merger,
            git, hooks);

        // Reject all changes.
        final ChangeSet.Id changeSetId =
          topicControl.getTopic().currChangeSetId();

        final List<ChangeSetElement> changes =
          db.changeSetElements().byChangeSet(changeSetId).toList();

        for (ChangeSetElement changeSetElement: changes) {
          final Change.Id changeId = changeSetElement.getChangeId();
          final Change change = db.changes().get(changeId);
          ChangeUtil.rejectStagedChange(change.currentPatchSetId(), user, db);
        }

        // Rebuild staging branch.
        final Branch.NameKey branch = topicControl.getTopic().getDest();
        ChangeUtil.rebuildStaging(branch, user, db, git, opFactory, merger,
            hooks);
      } catch (IOException e) {
        throw new IllegalStateException(e.getMessage());
      } catch (NoSuchRefException e) {
        throw new IllegalStateException(e.getMessage());
      } finally {
        // Make sure that access to Git repository is closed.
        if (git != null) {
          git.close();
        }
      }
      return topicDetailFactory.create(topicId).call();
    } else {
      // Report error message to user. User cannot move this change to staging.
      // The problem is caused because of illegal stage of missing access
      // rights.
      throw new IllegalStateException(result.getMessage());
    }
  }
}