comparison src/org/tmatesoft/hg/core/HgRevertCommand.java @ 526:2f9ed6bcefa2

Initial support for Revert command with accompanying minor refactoring
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 15 Jan 2013 17:07:19 +0100
parents
children 78a9e26e670d
comparison
equal deleted inserted replaced
525:0be5be8d57e9 526:2f9ed6bcefa2
1 /*
2 * Copyright (c) 2013 TMate Software Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * For information on how to redistribute this software under
14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com
16 */
17 package org.tmatesoft.hg.core;
18
19 import java.io.File;
20 import java.util.Arrays;
21 import java.util.LinkedHashSet;
22 import java.util.Set;
23
24 import org.tmatesoft.hg.internal.DirstateBuilder;
25 import org.tmatesoft.hg.internal.DirstateReader;
26 import org.tmatesoft.hg.internal.Experimental;
27 import org.tmatesoft.hg.internal.Internals;
28 import org.tmatesoft.hg.repo.HgInvalidRevisionException;
29 import org.tmatesoft.hg.repo.HgManifest;
30 import org.tmatesoft.hg.repo.HgRepository;
31 import org.tmatesoft.hg.repo.HgRuntimeException;
32 import org.tmatesoft.hg.repo.HgManifest.Flags;
33 import org.tmatesoft.hg.util.CancelledException;
34 import org.tmatesoft.hg.util.Path;
35
36 /**
37 * WORK IN PROGRESS.
38 *
39 * Restore files to their checkout state, 'hg revert' counterpart.
40 *
41 * @author Artem Tikhomirov
42 * @author TMate Software Ltd.
43 */
44 @Experimental(reason="Work in progress")
45 public class HgRevertCommand extends HgAbstractCommand<HgRevertCommand> {
46
47 private final HgRepository repo;
48 private final Set<Path> files = new LinkedHashSet<Path>();
49 private int changesetToCheckout = HgRepository.WORKING_COPY; // XXX WORKING_COPY_PARENT, in fact
50 private boolean keepOriginal = true;
51
52 public HgRevertCommand(HgRepository hgRepo) {
53 repo = hgRepo;
54 }
55
56 /**
57 * Additive
58 *
59 * @param paths files to revert
60 * @return <code>this</code> for convenience
61 */
62 public HgRevertCommand file(Path... paths) {
63 files.addAll(Arrays.asList(paths));
64 return this;
65 }
66
67 /**
68 * Revert the given files to their states as of a specific revision
69 *
70 * @param changesetRevIndex
71 * @return <code>this</code> for convenience
72 * @throws HgBadArgumentException
73 */
74 public HgRevertCommand changeset(int changesetRevIndex) throws HgBadArgumentException {
75 int lastCsetIndex = repo.getChangelog().getLastRevision();
76 if (changesetRevIndex < 0 || changesetRevIndex > lastCsetIndex) {
77 throw new HgBadArgumentException(String.format("Bad revision index %d, value from [0..%d] expected", changesetRevIndex, lastCsetIndex), null).setRevisionIndex(changesetRevIndex);
78 }
79 changesetToCheckout = changesetRevIndex;
80 return this;
81 }
82
83 /**
84 * Handy supplement to {@link #changeset(int)}
85 *
86 * @param revision
87 * @return <code>this</code> for convenience
88 * @throws HgBadArgumentException
89 */
90 public HgRevertCommand changeset(Nodeid revision) throws HgBadArgumentException {
91 try {
92 return changeset(repo.getChangelog().getRevisionIndex(revision));
93 } catch (HgInvalidRevisionException ex) {
94 throw new HgBadArgumentException("Can't find revision", ex).setRevision(revision);
95 }
96 }
97
98 // TODO keepOriginal() to save .orig
99
100 /**
101 * Perform the back out for the given files
102 *
103 * @throws HgIOException
104 * @throws HgException
105 * @throws CancelledException
106 */
107 public void execute() throws HgException, CancelledException {
108 try {
109 final int csetRevision;
110 if (changesetToCheckout == HgRepository.WORKING_COPY) {
111 csetRevision = repo.getChangelog().getRevisionIndex(repo.getWorkingCopyParents().first());
112 } else {
113 csetRevision = changesetToCheckout;
114 }
115 Internals implRepo = Internals.getInstance(repo);
116 final DirstateBuilder dirstateBuilder = new DirstateBuilder(implRepo);
117 dirstateBuilder.fillFrom(new DirstateReader(implRepo, new Path.SimpleSource()));
118 final HgCheckoutCommand.CheckoutWorker worker = new HgCheckoutCommand.CheckoutWorker(implRepo);
119
120 HgManifest.Inspector insp = new HgManifest.Inspector() {
121
122 public boolean next(Nodeid nid, Path fname, Flags flags) {
123 if (worker.next(nid, fname, flags)) {
124 dirstateBuilder.recordUncertain(fname);
125 return true;
126 }
127 return false;
128 }
129
130 public boolean end(int manifestRevision) {
131 return false;
132 }
133
134 public boolean begin(int mainfestRevision, Nodeid nid, int changelogRevision) {
135 return true;
136 }
137 };
138
139 for (Path file : files) {
140 File f = new File(repo.getWorkingDir(), file.toString());
141 if (f.isFile()) {
142 if (keepOriginal) {
143 File copy = new File(f.getParentFile(), f.getName() + ".orig");
144 if (copy.exists()) {
145 copy.delete();
146 }
147 f.renameTo(copy);
148 } else {
149 f.delete();
150 }
151 }
152 repo.getManifest().walkFileRevisions(file, insp, csetRevision);
153 worker.checkFailed();
154 }
155 dirstateBuilder.serialize();
156 } catch (HgRuntimeException ex) {
157 throw new HgLibraryFailureException(ex);
158 }
159 }
160 }