1 /*
2 * Copyright (C) 2009-2010, Google Inc.
3 * Copyright (C) 2009, Robin Rosenberg
4 * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com>
5 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * and other copyright owners as documented in the project's IP log.
7 *
8 * This program and the accompanying materials are made available
9 * under the terms of the Eclipse Distribution License v1.0 which
10 * accompanies this distribution, is reproduced below, and is
11 * available at http://www.eclipse.org/org/documents/edl-v10.php
12 *
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
17 * conditions are met:
18 *
19 * - Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * - Redistributions in binary form must reproduce the above
23 * copyright notice, this list of conditions and the following
24 * disclaimer in the documentation and/or other materials provided
25 * with the distribution.
26 *
27 * - Neither the name of the Eclipse Foundation, Inc. nor the
28 * names of its contributors may be used to endorse or promote
29 * products derived from this software without specific prior
30 * written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
33 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
34 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
37 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
44 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 */
46
47 package org.eclipse.jgit.lib;
48
49 import java.io.IOException;
50
51 import org.eclipse.jgit.lib.RefUpdate.Result;
52
53 /**
54 * A RefUpdate combination for renaming a reference.
55 * <p>
56 * If the source reference is currently pointed to by {@code HEAD}, then the
57 * HEAD symbolic reference is updated to point to the new destination.
58 */
59 public abstract class RefRename {
60 /** Update operation to read and delete the source reference. */
61 protected final RefUpdate source;
62
63 /** Update operation to create/overwrite the destination reference. */
64 protected final RefUpdate destination;
65
66 private Result result = Result.NOT_ATTEMPTED;
67
68 /**
69 * Initialize a new rename operation.
70 *
71 * @param src
72 * operation to read and delete the source.
73 * @param dst
74 * operation to create (or overwrite) the destination.
75 */
76 protected RefRename(RefUpdate="../../../../org/eclipse/jgit/lib/RefUpdate.html#RefUpdate">RefUpdate src, RefUpdate dst) {
77 source = src;
78 destination = dst;
79
80 String cmd = ""; //$NON-NLS-1$
81 if (source.getName().startsWith(Constants.R_HEADS)
82 && destination.getName().startsWith(Constants.R_HEADS))
83 cmd = "Branch: "; //$NON-NLS-1$
84 setRefLogMessage(cmd + "renamed " //$NON-NLS-1$
85 + Repository.shortenRefName(source.getName()) + " to " //$NON-NLS-1$
86 + Repository.shortenRefName(destination.getName()));
87 }
88
89 /**
90 * Get identity of the user making the change in the reflog.
91 *
92 * @return identity of the user making the change in the reflog.
93 */
94 public PersonIdent getRefLogIdent() {
95 return destination.getRefLogIdent();
96 }
97
98 /**
99 * Set the identity of the user appearing in the reflog.
100 * <p>
101 * The timestamp portion of the identity is ignored. A new identity with the
102 * current timestamp will be created automatically when the rename occurs
103 * and the log record is written.
104 *
105 * @param pi
106 * identity of the user. If null the identity will be
107 * automatically determined based on the repository
108 * configuration.
109 */
110 public void setRefLogIdent(PersonIdent pi) {
111 destination.setRefLogIdent(pi);
112 }
113
114 /**
115 * Get the message to include in the reflog.
116 *
117 * @return message the caller wants to include in the reflog; null if the
118 * rename should not be logged.
119 */
120 public String getRefLogMessage() {
121 return destination.getRefLogMessage();
122 }
123
124 /**
125 * Set the message to include in the reflog.
126 *
127 * @param msg
128 * the message to describe this change.
129 */
130 public void setRefLogMessage(String msg) {
131 if (msg == null)
132 disableRefLog();
133 else
134 destination.setRefLogMessage(msg, false);
135 }
136
137 /**
138 * Don't record this rename in the ref's associated reflog.
139 */
140 public void disableRefLog() {
141 destination.setRefLogMessage("", false); //$NON-NLS-1$
142 }
143
144 /**
145 * Get result of rename operation
146 *
147 * @return result of rename operation
148 */
149 public Result getResult() {
150 return result;
151 }
152
153 /**
154 * Rename
155 *
156 * @return the result of the new ref update
157 * @throws java.io.IOException
158 */
159 public Result rename() throws IOException {
160 try {
161 result = doRename();
162 return result;
163 } catch (IOException err) {
164 result = Result.IO_FAILURE;
165 throw err;
166 }
167 }
168
169 /**
170 * Do the actual rename
171 *
172 * @return the result of the rename operation.
173 * @throws java.io.IOException
174 */
175 protected abstract Result doRename() throws IOException;
176
177 /**
178 * Whether the {@code Constants#HEAD} reference needs to be linked to the
179 * new destination name.
180 *
181 * @return true if the {@code Constants#HEAD} reference needs to be linked
182 * to the new destination name.
183 * @throws java.io.IOException
184 * the current value of {@code HEAD} cannot be read.
185 */
186 protected boolean needToUpdateHEAD() throws IOException {
187 Ref head = source.getRefDatabase().exactRef(Constants.HEAD);
188 if (head != null && head.isSymbolic()) {
189 head = head.getTarget();
190 return head.getName().equals(source.getName());
191 }
192 return false;
193 }
194 }