17
17
import com .google .gerrit .extensions .webui .UiAction ;
18
18
import com .google .gerrit .reviewdb .client .Branch ;
19
19
import com .google .gerrit .reviewdb .client .Change ;
20
+ import com .google .gerrit .reviewdb .client .PatchSet ;
20
21
import com .google .gerrit .reviewdb .client .Project ;
21
22
import com .google .gerrit .reviewdb .client .RevId ;
23
+ import com .google .gerrit .reviewdb .client .Change .Status ;
22
24
import com .google .gerrit .server .IdentifiedUser ;
23
25
import com .google .gerrit .server .ProjectUtil ;
24
26
import com .google .gerrit .server .account .AccountResolver ;
33
35
import com .google .gerrit .server .project .NoSuchRefException ;
34
36
import com .google .gerrit .server .project .ProjectCache ;
35
37
import com .google .gerrit .server .query .change .ChangeData ;
38
+ import com .google .gerrit .server .query .change .InternalChangeQuery ;
36
39
import com .google .gerrit .server .submit .IntegrationException ;
37
40
import com .google .gerrit .server .submit .MergeOp ;
38
41
import com .google .gerrit .server .update .UpdateException ;
39
42
import com .google .inject .Inject ;
43
+ import com .google .inject .Provider ;
40
44
import com .google .inject .Singleton ;
45
+
41
46
import java .io .IOException ;
47
+ import java .util .List ;
42
48
import java .util .Map ;
43
49
import org .eclipse .jgit .errors .ConfigInvalidException ;
44
50
import org .eclipse .jgit .errors .RepositoryNotFoundException ;
45
51
import org .eclipse .jgit .lib .Config ;
46
52
import org .eclipse .jgit .lib .ObjectId ;
47
53
import org .eclipse .jgit .lib .RefUpdate .Result ;
48
54
import org .eclipse .jgit .lib .Repository ;
55
+ import org .eclipse .jgit .revwalk .RevCommit ;
56
+ import org .eclipse .jgit .revwalk .RevWalk ;
49
57
50
58
@ Singleton
51
59
public class QtStage
@@ -70,6 +78,7 @@ private Output(Change c) {
70
78
private final GitReferenceUpdated referenceUpdated ;
71
79
private final QtCherryPickPatch qtCherryPickPatch ;
72
80
private final QtUtil qtUtil ;
81
+ private final Provider <InternalChangeQuery > queryProvider ;
73
82
74
83
private final AccountResolver accountResolver ;
75
84
private final String label ;
@@ -90,7 +99,8 @@ private Output(Change c) {
90
99
ProjectCache projectCache ,
91
100
GitReferenceUpdated referenceUpdated ,
92
101
QtCherryPickPatch qtCherryPickPatch ,
93
- QtUtil qtUtil ) {
102
+ QtUtil qtUtil ,
103
+ Provider <InternalChangeQuery > queryProvider ) {
94
104
95
105
this .repoManager = repoManager ;
96
106
this .permissionBackend = permissionBackend ;
@@ -105,6 +115,7 @@ private Output(Change c) {
105
115
this .referenceUpdated = referenceUpdated ;
106
116
this .qtCherryPickPatch = qtCherryPickPatch ;
107
117
this .qtUtil = qtUtil ;
118
+ this .queryProvider = queryProvider ;
108
119
}
109
120
110
121
@ Override
@@ -171,6 +182,8 @@ private Change changeToStaging(RevisionResource rsrc, IdentifiedUser submitter,
171
182
if (sourceId == null )
172
183
throw new NoSuchRefException ("Invalid Revision: " + rsrc .getPatchSet ().getRevision ().get ());
173
184
185
+ checkParents (git , rsrc );
186
+
174
187
changeData = changeDataFactory .create (change );
175
188
MergeOp .checkSubmitRule (changeData , false );
176
189
@@ -214,6 +227,36 @@ private Change changeToStaging(RevisionResource rsrc, IdentifiedUser submitter,
214
227
}
215
228
}
216
229
230
+ private void checkParents (RevisionResource resource ) throws ResourceConflictException {
231
+ try (final Repository repository = repoManager .openRepository (resource .getProject ())) {
232
+ checkParents (repository , resource );
233
+ } catch (IOException e ) {
234
+ throw new ResourceConflictException ("Can not read repository." , e );
235
+ }
236
+ }
237
+
238
+ private void checkParents (Repository repository , RevisionResource resource ) throws ResourceConflictException {
239
+ try (final RevWalk rw = new RevWalk (repository )) {
240
+ final PatchSet ps = resource .getPatchSet ();
241
+ final RevCommit rc = rw .parseCommit (ObjectId .fromString (ps .getRevision ().get ()));
242
+ if (rc .getParentCount () < 2 ) {
243
+ return ;
244
+ }
245
+ for (final RevCommit parent : rc .getParents ()) {
246
+ final List <ChangeData > changes =
247
+ queryProvider .get ().enforceVisibility (true ).byProjectCommit (resource .getProject (), parent );
248
+ for (ChangeData cd : changes ) {
249
+ final Change change = cd .change ();
250
+ if (change .getStatus () != Status .MERGED ) {
251
+ throw new ResourceConflictException (String .format ("Can not stage: Parent \" %s\" of a merged commit is not merged." , parent .name ()));
252
+ }
253
+ }
254
+ }
255
+ } catch (IOException e ) {
256
+ throw new ResourceConflictException ("Can not read repository." , e );
257
+ }
258
+ }
259
+
217
260
@ Override
218
261
public UiAction .Description getDescription (RevisionResource resource ) {
219
262
Change change = resource .getChange ();
@@ -223,6 +266,12 @@ public UiAction.Description getDescription(RevisionResource resource) {
223
266
|| !resource .permissions ().testOrFalse (ChangePermission .QT_STAGE )) {
224
267
return null ; // submit not visible
225
268
}
269
+ try {
270
+ checkParents (resource );
271
+ } catch (ResourceConflictException e ) {
272
+ logger .atWarning ().log ("Parent(s) check failed. %s" , e .getMessage ());
273
+ return null ;
274
+ }
226
275
try {
227
276
if (!projectCache .checkedGet (resource .getProject ()).statePermitsWrite ()) {
228
277
return null ; // stage not visible
0 commit comments