Mercurial > jhg
annotate src/org/tmatesoft/hg/internal/COWTransaction.java @ 686:f1f095e42555
Annotated file is not always changed in the latest changeset, need to find out last changest it was changed at (iow, diffed to with BlameHelper)
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 25 Jul 2013 22:12:14 +0200 |
parents | dde18bc7053b |
children |
rev | line source |
---|---|
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
1 /* |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
2 * Copyright (c) 2013 TMate Software Ltd |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
3 * |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
4 * This program is free software; you can redistribute it and/or modify |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
5 * it under the terms of the GNU General Public License as published by |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
6 * the Free Software Foundation; version 2 of the License. |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
7 * |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
8 * This program is distributed in the hope that it will be useful, |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
11 * GNU General Public License for more details. |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
12 * |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
13 * For information on how to redistribute this software under |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
14 * the terms of a license other than GNU General Public License |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
15 * contact TMate Software at support@hg4j.com |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
16 */ |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
17 package org.tmatesoft.hg.internal; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
18 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
19 import java.io.File; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
20 import java.io.IOException; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
21 import java.util.Iterator; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
22 import java.util.LinkedList; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
23 import java.util.List; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
24 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
25 import org.tmatesoft.hg.core.HgIOException; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
26 import org.tmatesoft.hg.core.SessionContext; |
665
dde18bc7053b
Test Copy-on-Write transactions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
654
diff
changeset
|
27 import org.tmatesoft.hg.repo.HgInvalidStateException; |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
28 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
29 /** |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
30 * This transaction strategy makes a copy of original file and breaks origin hard links, if any. |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
31 * Changes are directed to actual repository files. |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
32 * |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
33 * On commit, remove all backup copies |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
34 * On rollback, move all backup files in place of original |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
35 * |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
36 * @author Artem Tikhomirov |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
37 * @author TMate Software Ltd. |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
38 */ |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
39 public final class COWTransaction extends Transaction { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
40 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
41 private final FileUtils fileHelper; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
42 private final List<RollbackEntry> entries = new LinkedList<RollbackEntry>(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
43 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
44 public COWTransaction(SessionContext.Source ctxSource) { |
654
12a4f60ea972
1) Console push tool. 2) Pass class to blame into FileUtils
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
635
diff
changeset
|
45 fileHelper = new FileUtils(ctxSource.getSessionContext().getLog(), this); |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
46 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
47 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
48 @Override |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
49 public File prepare(File f) throws HgIOException { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
50 if (known(f)) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
51 return f; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
52 } |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
53 if (!f.exists()) { |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
54 return recordNonExistent(f); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
55 } |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
56 final File parentDir = f.getParentFile(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
57 assert parentDir.canWrite(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
58 File copy = new File(parentDir, f.getName() + ".hg4j.copy"); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
59 fileHelper.copy(f, copy); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
60 final long lm = f.lastModified(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
61 copy.setLastModified(lm); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
62 File backup = new File(parentDir, f.getName() + ".hg4j.orig"); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
63 if (backup.exists()) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
64 backup.delete(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
65 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
66 if (!f.renameTo(backup)) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
67 throw new HgIOException(String.format("Failed to backup %s to %s", f.getName(), backup.getName()), backup); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
68 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
69 if (!copy.renameTo(f)) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
70 throw new HgIOException(String.format("Failed to bring on-write copy in place (%s to %s)", copy.getName(), f.getName()), copy); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
71 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
72 f.setLastModified(lm); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
73 record(f, backup); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
74 return f; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
75 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
76 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
77 @Override |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
78 public File prepare(File origin, File backup) throws HgIOException { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
79 if (known(origin)) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
80 return origin; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
81 } |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
82 if (!origin.exists()) { |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
83 return recordNonExistent(origin); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
84 } |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
85 fileHelper.copy(origin, backup); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
86 final RollbackEntry e = record(origin, backup); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
87 e.keepBackup = true; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
88 return origin; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
89 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
90 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
91 @Override |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
92 public void done(File f) throws HgIOException { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
93 find(f).success = true; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
94 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
95 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
96 @Override |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
97 public void failure(File f, IOException ex) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
98 find(f).failure = ex; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
99 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
100 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
101 // XXX custom exception for commit and rollback to hold information about files rolled back |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
102 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
103 @Override |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
104 public void commit() throws HgIOException { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
105 for (Iterator<RollbackEntry> it = entries.iterator(); it.hasNext();) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
106 RollbackEntry e = it.next(); |
665
dde18bc7053b
Test Copy-on-Write transactions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
654
diff
changeset
|
107 if (!e.success) { |
dde18bc7053b
Test Copy-on-Write transactions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
654
diff
changeset
|
108 throw new HgInvalidStateException(String.format("Attempt to commit transaction without successful clearance of file %s", e.origin)); |
dde18bc7053b
Test Copy-on-Write transactions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
654
diff
changeset
|
109 } |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
110 if (e.failure != null) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
111 throw new HgIOException("Can't close transaction with a failure.", e.failure, e.origin); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
112 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
113 if (!e.keepBackup && e.backup != null) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
114 e.backup.delete(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
115 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
116 it.remove(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
117 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
118 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
119 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
120 @Override |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
121 public void rollback() throws HgIOException { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
122 LinkedList<RollbackEntry> success = new LinkedList<RollbackEntry>(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
123 for (Iterator<RollbackEntry> it = entries.iterator(); it.hasNext();) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
124 RollbackEntry e = it.next(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
125 e.origin.delete(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
126 if (e.backup != null) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
127 if (!e.backup.renameTo(e.origin)) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
128 String msg = String.format("Transaction rollback failed, could not rename backup %s back to %s", e.backup.getName(), e.origin.getName()); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
129 throw new HgIOException(msg, e.origin); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
130 } |
621
99ad1e3a4e4d
RevlogStream: be aware of existence (not HgDataFile), facilitate use of an added HgDataFile over a commit; Rollback: be more sensitive about file changes (file size is not enough: write/rollback leaves it intact); tests
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
617
diff
changeset
|
131 // renameTo() doesn't update timestamp, while the rest of the code relies |
99ad1e3a4e4d
RevlogStream: be aware of existence (not HgDataFile), facilitate use of an added HgDataFile over a commit; Rollback: be more sensitive about file changes (file size is not enough: write/rollback leaves it intact); tests
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
617
diff
changeset
|
132 // on file timestamp to detect revlog changes. Rollback *is* a change, |
99ad1e3a4e4d
RevlogStream: be aware of existence (not HgDataFile), facilitate use of an added HgDataFile over a commit; Rollback: be more sensitive about file changes (file size is not enough: write/rollback leaves it intact); tests
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
617
diff
changeset
|
133 // even if it brings the old state. |
99ad1e3a4e4d
RevlogStream: be aware of existence (not HgDataFile), facilitate use of an added HgDataFile over a commit; Rollback: be more sensitive about file changes (file size is not enough: write/rollback leaves it intact); tests
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
617
diff
changeset
|
134 e.origin.setLastModified(System.currentTimeMillis()); |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
135 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
136 success.add(e); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
137 it.remove(); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
138 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
139 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
140 |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
141 private File recordNonExistent(File f) throws HgIOException { |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
142 record(f, null); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
143 try { |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
144 f.getParentFile().mkdirs(); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
145 f.createNewFile(); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
146 return f; |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
147 } catch (IOException ex) { |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
148 throw new HgIOException("Failed to create new file", ex, f); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
149 } |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
150 } |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
151 |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
152 private RollbackEntry record(File origin, File backup) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
153 final RollbackEntry e = new RollbackEntry(origin, backup); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
154 entries.add(e); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
155 return e; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
156 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
157 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
158 private boolean known(File f) { |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
159 RollbackEntry e = lookup(f); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
160 return e != null; |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
161 } |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
162 |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
163 private RollbackEntry find(File f) { |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
164 RollbackEntry e = lookup(f); |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
165 if (e != null) { |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
166 return e; |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
167 } |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
168 assert false; |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
169 return new RollbackEntry(f,f); |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
170 } |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
171 |
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
172 private RollbackEntry lookup(File f) { |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
173 for (RollbackEntry e : entries) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
174 if (e.origin.equals(f)) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
175 return e; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
176 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
177 } |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
178 return null; |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
179 } |
635
4ec2d44e2bf3
Compound test scenario for checkout, add, remove, revert and commit
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
621
diff
changeset
|
180 |
617
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
181 private static class RollbackEntry { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
182 public final File origin; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
183 public final File backup; // may be null to indicate file didn't exist |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
184 public boolean success = false; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
185 public IOException failure = null; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
186 public boolean keepBackup = false; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
187 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
188 public RollbackEntry(File o, File b) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
189 origin = o; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
190 backup = b; |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
191 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
192 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
193 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
194 public static class Factory implements Transaction.Factory { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
195 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
196 public Transaction create(SessionContext.Source ctxSource) { |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
197 return new COWTransaction(ctxSource); |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
198 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
199 |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
200 } |
65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
201 } |