View Javadoc
1   /*
2    * Copyright (C) 2016, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.internal.storage.reftree;
12  
13  import static org.eclipse.jgit.lib.Ref.Storage.LOOSE;
14  import static org.eclipse.jgit.lib.Ref.Storage.NEW;
15  
16  import java.io.IOException;
17  import java.util.Collections;
18  
19  import org.eclipse.jgit.annotations.Nullable;
20  import org.eclipse.jgit.errors.MissingObjectException;
21  import org.eclipse.jgit.lib.ObjectId;
22  import org.eclipse.jgit.lib.ObjectIdRef;
23  import org.eclipse.jgit.lib.Ref;
24  import org.eclipse.jgit.lib.RefDatabase;
25  import org.eclipse.jgit.lib.RefUpdate;
26  import org.eclipse.jgit.lib.Repository;
27  import org.eclipse.jgit.lib.SymbolicRef;
28  import org.eclipse.jgit.revwalk.RevObject;
29  import org.eclipse.jgit.revwalk.RevTag;
30  import org.eclipse.jgit.revwalk.RevWalk;
31  import org.eclipse.jgit.transport.ReceiveCommand;
32  
33  /** Single reference update to {@link RefTreeDatabase}. */
34  class RefTreeUpdate extends RefUpdate {
35  	private final RefTreeDatabase refdb;
36  	private RevWalk rw;
37  	private RefTreeBatch batch;
38  	private Ref oldRef;
39  
40  	RefTreeUpdate(RefTreeDatabase refdb, Ref ref) {
41  		super(ref);
42  		this.refdb = refdb;
43  		setCheckConflicting(false); // Done automatically by doUpdate.
44  	}
45  
46  	/** {@inheritDoc} */
47  	@Override
48  	protected RefDatabase getRefDatabase() {
49  		return refdb;
50  	}
51  
52  	/** {@inheritDoc} */
53  	@Override
54  	protected Repository getRepository() {
55  		return refdb.getRepository();
56  	}
57  
58  	/** {@inheritDoc} */
59  	@Override
60  	protected boolean tryLock(boolean deref) throws IOException {
61  		rw = new RevWalk(getRepository());
62  		batch = new RefTreeBatch(refdb);
63  		batch.init(rw);
64  		oldRef = batch.exactRef(rw.getObjectReader(), getName());
65  		if (oldRef != null && oldRef.getObjectId() != null) {
66  			setOldObjectId(oldRef.getObjectId());
67  		} else if (oldRef == null && getExpectedOldObjectId() != null) {
68  			setOldObjectId(ObjectId.zeroId());
69  		}
70  		return true;
71  	}
72  
73  	/** {@inheritDoc} */
74  	@Override
75  	protected void unlock() {
76  		batch = null;
77  		if (rw != null) {
78  			rw.close();
79  			rw = null;
80  		}
81  	}
82  
83  	/** {@inheritDoc} */
84  	@Override
85  	protected Result doUpdate(Result desiredResult) throws IOException {
86  		return run(newRef(getName(), getNewObjectId()), desiredResult);
87  	}
88  
89  	private Ref newRef(String name, ObjectId id)
90  			throws MissingObjectException, IOException {
91  		RevObject o = rw.parseAny(id);
92  		if (o instanceof RevTag) {
93  			RevObject p = rw.peel(o);
94  			return new ObjectIdRef.PeeledTag(LOOSE, name, id, p.copy());
95  		}
96  		return new ObjectIdRef.PeeledNonTag(LOOSE, name, id);
97  	}
98  
99  	/** {@inheritDoc} */
100 	@Override
101 	protected Result doDelete(Result desiredResult) throws IOException {
102 		return run(null, desiredResult);
103 	}
104 
105 	/** {@inheritDoc} */
106 	@Override
107 	protected Result doLink(String target) throws IOException {
108 		Ref dst = new ObjectIdRef.Unpeeled(NEW, target, null);
109 		SymbolicRef n = new SymbolicRef(getName(), dst);
110 		Result desiredResult = getRef().getStorage() == NEW
111 			? Result.NEW
112 			: Result.FORCED;
113 		return run(n, desiredResult);
114 	}
115 
116 	private Result run(@Nullable Ref newRef, Result desiredResult)
117 			throws IOException {
118 		Command c = new Command(oldRef, newRef);
119 		batch.setRefLogIdent(getRefLogIdent());
120 		batch.setRefLogMessage(getRefLogMessage(), isRefLogIncludingResult());
121 		batch.execute(rw, Collections.singletonList(c));
122 		return translate(c.getResult(), desiredResult);
123 	}
124 
125 	static Result translate(ReceiveCommand.Result r, Result desiredResult) {
126 		switch (r) {
127 		case OK:
128 			return desiredResult;
129 
130 		case LOCK_FAILURE:
131 			return Result.LOCK_FAILURE;
132 
133 		case NOT_ATTEMPTED:
134 			return Result.NOT_ATTEMPTED;
135 
136 		case REJECTED_MISSING_OBJECT:
137 			return Result.IO_FAILURE;
138 
139 		case REJECTED_CURRENT_BRANCH:
140 			return Result.REJECTED_CURRENT_BRANCH;
141 
142 		case REJECTED_OTHER_REASON:
143 		case REJECTED_NOCREATE:
144 		case REJECTED_NODELETE:
145 		case REJECTED_NONFASTFORWARD:
146 		default:
147 			return Result.REJECTED;
148 		}
149 	}
150 }