annotate src/org/tmatesoft/hg/internal/BundleGenerator.java @ 668:d25f0324a27a

Delete bundle with push/pull changes once command completes successfully. Test for bundle generator
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 11 Jul 2013 18:41:40 +0200
parents fba85bc1dfb8
children 52af7f62e731
rev   line source
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
1 /*
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
2 * Copyright (c) 2013 TMate Software Ltd
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
3 *
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
4 * This program is free software; you can redistribute it and/or modify
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
5 * it under the terms of the GNU General Public License as published by
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
6 * the Free Software Foundation; version 2 of the License.
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
7 *
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
8 * This program is distributed in the hope that it will be useful,
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
11 * GNU General Public License for more details.
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
12 *
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
13 * For information on how to redistribute this software under
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
14 * the terms of a license other than GNU General Public License
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
15 * contact TMate Software at support@hg4j.com
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
16 */
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
17 package org.tmatesoft.hg.internal;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
18
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
19 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
20 import static org.tmatesoft.hg.repo.HgRepository.TIP;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
21
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
22 import java.io.File;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
23 import java.io.FileOutputStream;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
24 import java.io.IOException;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
25 import java.util.ArrayList;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
26 import java.util.Arrays;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
27 import java.util.Collection;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
28 import java.util.Collections;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
29 import java.util.Comparator;
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
30 import java.util.HashSet;
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
31 import java.util.List;
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
32 import java.util.Set;
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
33
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
34 import org.tmatesoft.hg.core.HgIOException;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
35 import org.tmatesoft.hg.core.Nodeid;
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
36 import org.tmatesoft.hg.internal.DataSerializer.OutputStreamSerializer;
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
37 import org.tmatesoft.hg.internal.Patch.PatchDataSource;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
38 import org.tmatesoft.hg.repo.HgChangelog;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
39 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
40 import org.tmatesoft.hg.repo.HgDataFile;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
41 import org.tmatesoft.hg.repo.HgInvalidControlFileException;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
42 import org.tmatesoft.hg.repo.HgManifest;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
43 import org.tmatesoft.hg.repo.HgRuntimeException;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
44
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
45 /**
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
46 * @see http://mercurial.selenic.com/wiki/BundleFormat
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
47 * @author Artem Tikhomirov
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
48 * @author TMate Software Ltd.
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
49 */
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
50 public class BundleGenerator {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
51
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
52 private final Internals repo;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
53
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
54 public BundleGenerator(Internals hgRepo) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
55 repo = hgRepo;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
56 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
57
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
58 public File create(List<Nodeid> changesets) throws HgIOException, IOException {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
59 final HgChangelog clog = repo.getRepo().getChangelog();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
60 final HgManifest manifest = repo.getRepo().getManifest();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
61 IntVector clogRevsVector = new IntVector(changesets.size(), 0);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
62 for (Nodeid n : changesets) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
63 clogRevsVector.add(clog.getRevisionIndex(n));
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
64 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
65 clogRevsVector.sort(true);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
66 final int[] clogRevs = clogRevsVector.toArray();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
67 final IntMap<Nodeid> clogMap = new IntMap<Nodeid>(changesets.size());
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
68 final IntVector manifestRevs = new IntVector(changesets.size(), 0);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
69 final List<HgDataFile> files = new ArrayList<HgDataFile>();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
70 clog.range(new HgChangelog.Inspector() {
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
71 private Set<String> seenFiles = new HashSet<String>();
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
72 public void next(int revisionIndex, Nodeid nodeid, RawChangeset cset) throws HgRuntimeException {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
73 clogMap.put(revisionIndex, nodeid);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
74 manifestRevs.add(manifest.getRevisionIndex(cset.manifest()));
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
75 for (String f : cset.files()) {
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
76 if (seenFiles.contains(f)) {
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
77 continue;
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
78 }
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
79 seenFiles.add(f);
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
80 HgDataFile df = repo.getRepo().getFileNode(f);
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
81 files.add(df);
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
82 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
83 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
84 }, clogRevs);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
85 manifestRevs.sort(true);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
86 //
651
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
87 final File bundleFile = File.createTempFile("hg4j-", ".bundle");
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
88 final FileOutputStream osBundle = new FileOutputStream(bundleFile);
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
89 final OutputStreamSerializer outRaw = new OutputStreamSerializer(osBundle);
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
90 outRaw.write("HG10UN".getBytes(), 0, 6);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
91 //
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
92 RevlogStream clogStream = repo.getImplAccess().getChangelogStream();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
93 new ChunkGenerator(outRaw, clogMap).iterate(clogStream, clogRevs);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
94 outRaw.writeInt(0); // null chunk for changelog group
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
95 //
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
96 RevlogStream manifestStream = repo.getImplAccess().getManifestStream();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
97 new ChunkGenerator(outRaw, clogMap).iterate(manifestStream, manifestRevs.toArray(true));
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
98 outRaw.writeInt(0); // null chunk for manifest group
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
99 //
667
fba85bc1dfb8 Refactoring: move all encoding/decoding operations into single place, EncodingHelper
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 651
diff changeset
100 EncodingHelper fnEncoder = repo.buildFileNameEncodingHelper();
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
101 for (HgDataFile df : sortedByName(files)) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
102 RevlogStream s = repo.getImplAccess().getStream(df);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
103 final IntVector fileRevs = new IntVector();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
104 s.iterate(0, TIP, false, new RevlogStream.Inspector() {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
105
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
106 public void next(int revisionIndex, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
107 if (Arrays.binarySearch(clogRevs, linkRevision) >= 0) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
108 fileRevs.add(revisionIndex);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
109 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
110 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
111 });
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
112 fileRevs.sort(true);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
113 if (!fileRevs.isEmpty()) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
114 // although BundleFormat page says "filename length, filename" for a file,
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
115 // in fact there's a sort of 'filename chunk', i.e. filename length field includes
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
116 // not only length of filename, but also length of the field itseld, i.e. filename.length+sizeof(int)
667
fba85bc1dfb8 Refactoring: move all encoding/decoding operations into single place, EncodingHelper
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 651
diff changeset
117 byte[] fnameBytes = fnEncoder.toBundle(df.getPath());
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
118 outRaw.writeInt(fnameBytes.length + 4);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
119 outRaw.writeByte(fnameBytes);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
120 new ChunkGenerator(outRaw, clogMap).iterate(s, fileRevs.toArray(true));
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
121 outRaw.writeInt(0); // null chunk for file group
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
122 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
123 }
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
124 outRaw.writeInt(0); // null chunk to indicate no more files (although BundleFormat page doesn't mention this)
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
125 outRaw.done();
645
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
126 osBundle.flush();
14dac192aa26 Push: phase2 - upload bundle with changes to remote server
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 644
diff changeset
127 osBundle.close();
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
128 //return new HgBundle(repo.getSessionContext(), repo.getDataAccess(), bundleFile);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
129 return bundleFile;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
130 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
131
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
132 private static Collection<HgDataFile> sortedByName(List<HgDataFile> files) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
133 Collections.sort(files, new Comparator<HgDataFile>() {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
134
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
135 public int compare(HgDataFile o1, HgDataFile o2) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
136 return o1.getPath().compareTo(o2.getPath());
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
137 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
138 });
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
139 return files;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
140 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
141
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
142 private static class ChunkGenerator implements RevlogStream.Inspector {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
143
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
144 private final DataSerializer ds;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
145 private final IntMap<Nodeid> parentMap;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
146 private final IntMap<Nodeid> clogMap;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
147 private byte[] prevContent;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
148 private int startParent;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
149
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
150 public ChunkGenerator(DataSerializer dataSerializer, IntMap<Nodeid> clogNodeidMap) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
151 ds = dataSerializer;
651
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
152 parentMap = new IntMap<Nodeid>(clogNodeidMap.size());
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
153 clogMap = clogNodeidMap;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
154 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
155
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
156 public void iterate(RevlogStream s, int[] revisions) throws HgRuntimeException {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
157 int[] p = s.parents(revisions[0], new int[2]);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
158 startParent = p[0];
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
159 int[] revs2read;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
160 if (startParent == NO_REVISION) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
161 revs2read = revisions;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
162 prevContent = new byte[0];
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
163 } else {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
164 revs2read = new int[revisions.length + 1];
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
165 revs2read[0] = startParent;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
166 System.arraycopy(revisions, 0, revs2read, 1, revisions.length);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
167 }
651
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
168 // FIXME this is a hack to fill parentsMap with
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
169 // parents of elements that we are not going to meet with regular
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
170 // iteration, e.g. changes from a different branch (with some older parent),
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
171 // scenario: two revisions added to two different branches
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
172 // revisions[10, 11], parents(10) == 9, parents(11) == 7
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
173 // revs2read == [9,10,11], and parentsMap lacks entry for parent rev7.
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
174 fillMissingParentsMap(s, revisions);
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
175 s.iterate(revs2read, true, this);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
176 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
177
651
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
178 private void fillMissingParentsMap(RevlogStream s, int[] revisions) throws HgRuntimeException {
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
179 int[] p = new int[2];
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
180 for (int i = 1; i < revisions.length; i++) {
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
181 s.parents(revisions[i], p);
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
182 if (p[0] != NO_REVISION && Arrays.binarySearch(revisions, p[0]) < 0) {
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
183 parentMap.put(p[0], Nodeid.fromBinary(s.nodeid(p[0]), 0));
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
184 }
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
185 if (p[1] != NO_REVISION && Arrays.binarySearch(revisions, p[1]) < 0) {
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
186 parentMap.put(p[1], Nodeid.fromBinary(s.nodeid(p[1]), 0));
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
187 }
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
188 }
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
189 }
6e98d34eaca8 Push: tests (push to empty, push changes, respect secret)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents: 645
diff changeset
190
644
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
191 public void next(int revisionIndex, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
192 try {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
193 parentMap.put(revisionIndex, Nodeid.fromBinary(nodeid, 0));
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
194 byte[] nextContent = data.byteArray();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
195 data.done();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
196 if (revisionIndex == startParent) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
197 prevContent = nextContent;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
198 return;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
199 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
200 Patch p = GeneratePatchInspector.delta(prevContent, nextContent);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
201 prevContent = nextContent;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
202 nextContent = null;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
203 PatchDataSource pds = p.new PatchDataSource();
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
204 int len = pds.serializeLength() + 84;
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
205 ds.writeInt(len);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
206 ds.write(nodeid, 0, Nodeid.SIZE);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
207 if (parent1Revision != NO_REVISION) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
208 ds.writeByte(parentMap.get(parent1Revision).toByteArray());
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
209 } else {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
210 ds.writeByte(Nodeid.NULL.toByteArray());
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
211 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
212 if (parent2Revision != NO_REVISION) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
213 ds.writeByte(parentMap.get(parent2Revision).toByteArray());
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
214 } else {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
215 ds.writeByte(Nodeid.NULL.toByteArray());
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
216 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
217 ds.writeByte(clogMap.get(linkRevision).toByteArray());
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
218 pds.serialize(ds);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
219 } catch (IOException ex) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
220 // XXX odd to have object with IOException to use where no checked exception is allowed
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
221 throw new HgInvalidControlFileException(ex.getMessage(), ex, null);
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
222 } catch (HgIOException ex) {
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
223 throw new HgInvalidControlFileException(ex, true); // XXX any way to refactor ChunkGenerator not to get checked exception here?
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
224 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
225 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
226 }
1deea2f33218 Push: phase1 - prepare bundle with changes
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff changeset
227 }