View Javadoc
1   /*
2    * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
3    * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
4    * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
5    *
6    * This program and the accompanying materials are made available under the
7    * terms of the Eclipse Distribution License v. 1.0 which is available at
8    * https://www.eclipse.org/org/documents/edl-v10.php.
9    *
10   * SPDX-License-Identifier: BSD-3-Clause
11   */
12  
13  package org.eclipse.jgit.transport;
14  
15  import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
16  
17  import org.eclipse.jgit.lib.AnyObjectId;
18  import org.eclipse.jgit.lib.ObjectId;
19  import org.eclipse.jgit.lib.RefUpdate;
20  
21  /**
22   * Update of a locally stored tracking branch.
23   */
24  public class TrackingRefUpdate {
25  	private final String remoteName;
26  	final String localName;
27  	boolean forceUpdate;
28  	ObjectId oldObjectId;
29  	ObjectId newObjectId;
30  
31  	private RefUpdate.Result result;
32  	private ReceiveCommand cmd;
33  
34  	TrackingRefUpdate(
35  			boolean canForceUpdate,
36  			String remoteName,
37  			String localName,
38  			AnyObjectId oldValue,
39  			AnyObjectId newValue) {
40  		this.remoteName = remoteName;
41  		this.localName = localName;
42  		this.forceUpdate = canForceUpdate;
43  		this.oldObjectId = oldValue.copy();
44  		this.newObjectId = newValue.copy();
45  	}
46  
47  	/**
48  	 * Get the name of the remote ref.
49  	 * <p>
50  	 * Usually this is of the form "refs/heads/master".
51  	 *
52  	 * @return the name used within the remote repository.
53  	 */
54  	public String getRemoteName() {
55  		return remoteName;
56  	}
57  
58  	/**
59  	 * Get the name of the local tracking ref.
60  	 * <p>
61  	 * Usually this is of the form "refs/remotes/origin/master".
62  	 *
63  	 * @return the name used within this local repository.
64  	 */
65  	public String getLocalName() {
66  		return localName;
67  	}
68  
69  	/**
70  	 * Get the new value the ref will be (or was) updated to.
71  	 *
72  	 * @return new value. Null if the caller has not configured it.
73  	 */
74  	public ObjectId getNewObjectId() {
75  		return newObjectId;
76  	}
77  
78  	/**
79  	 * The old value of the ref, prior to the update being attempted.
80  	 * <p>
81  	 * This value may differ before and after the update method. Initially it is
82  	 * populated with the value of the ref before the lock is taken, but the old
83  	 * value may change if someone else modified the ref between the time we
84  	 * last read it and when the ref was locked for update.
85  	 *
86  	 * @return the value of the ref prior to the update being attempted.
87  	 */
88  	public ObjectId getOldObjectId() {
89  		return oldObjectId;
90  	}
91  
92  	/**
93  	 * Get the status of this update.
94  	 *
95  	 * @return the status of the update.
96  	 */
97  	public RefUpdate.Result getResult() {
98  		return result;
99  	}
100 
101 	void setResult(RefUpdate.Result result) {
102 		this.result = result;
103 	}
104 
105 	/**
106 	 * Get this update wrapped by a ReceiveCommand.
107 	 *
108 	 * @return this update wrapped by a ReceiveCommand.
109 	 * @since 3.4
110 	 */
111 	public ReceiveCommand asReceiveCommand() {
112 		if (cmd == null)
113 			cmd = new Command();
114 		return cmd;
115 	}
116 
117 	final class Command extends ReceiveCommand {
118 		Command() {
119 			super(oldObjectId, newObjectId, localName);
120 		}
121 
122 		boolean canForceUpdate() {
123 			return forceUpdate;
124 		}
125 
126 		@Override
127 		public void setResult(RefUpdate.Result status) {
128 			result = status;
129 			super.setResult(status);
130 		}
131 
132 		@Override
133 		public void setResult(ReceiveCommand.Result status) {
134 			result = decode(status);
135 			super.setResult(status);
136 		}
137 
138 		@Override
139 		public void setResult(ReceiveCommand.Result status, String msg) {
140 			result = decode(status);
141 			super.setResult(status, msg);
142 		}
143 
144 		private RefUpdate.Result decode(ReceiveCommand.Result status) {
145 			switch (status) {
146 			case OK:
147 				if (AnyObjectId.isEqual(oldObjectId, newObjectId))
148 					return RefUpdate.Result.NO_CHANGE;
149 				switch (getType()) {
150 				case CREATE:
151 					return RefUpdate.Result.NEW;
152 				case UPDATE:
153 					return RefUpdate.Result.FAST_FORWARD;
154 				case DELETE:
155 				case UPDATE_NONFASTFORWARD:
156 				default:
157 					return RefUpdate.Result.FORCED;
158 				}
159 
160 			case REJECTED_NOCREATE:
161 			case REJECTED_NODELETE:
162 			case REJECTED_NONFASTFORWARD:
163 				return RefUpdate.Result.REJECTED;
164 			case REJECTED_CURRENT_BRANCH:
165 				return RefUpdate.Result.REJECTED_CURRENT_BRANCH;
166 			case REJECTED_MISSING_OBJECT:
167 				return RefUpdate.Result.IO_FAILURE;
168 			case LOCK_FAILURE:
169 			case NOT_ATTEMPTED:
170 			case REJECTED_OTHER_REASON:
171 			default:
172 				return RefUpdate.Result.LOCK_FAILURE;
173 			}
174 		}
175 	}
176 
177 	/** {@inheritDoc} */
178 	@SuppressWarnings("nls")
179 	@Override
180 	public String toString() {
181 		StringBuilder sb = new StringBuilder();
182 		sb.append("TrackingRefUpdate[");
183 		sb.append(remoteName);
184 		sb.append(" -> ");
185 		sb.append(localName);
186 		if (forceUpdate)
187 			sb.append(" (forced)");
188 		sb.append(" ");
189 		sb.append(oldObjectId == null ? ""
190 				: oldObjectId.abbreviate(OBJECT_ID_ABBREV_STRING_LENGTH)
191 						.name());
192 		sb.append("..");
193 		sb.append(newObjectId == null ? ""
194 				: newObjectId.abbreviate(OBJECT_ID_ABBREV_STRING_LENGTH)
195 						.name());
196 		sb.append("]");
197 		return sb.toString();
198 	}
199 }