2
This code is derived from jgit (http://eclipse.org/jgit).
3
Copyright owners are documented in jgit's IP log.
5
This program and the accompanying materials are made available
6
under the terms of the Eclipse Distribution License v1.0 which
7
accompanies this distribution, is reproduced below, and is
8
available at http://www.eclipse.org/org/documents/edl-v10.php
12
Redistribution and use in source and binary forms, with or
13
without modification, are permitted provided that the following
16
- Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
19
- Redistributions in binary form must reproduce the above
20
copyright notice, this list of conditions and the following
21
disclaimer in the documentation and/or other materials provided
22
with the distribution.
24
- Neither the name of the Eclipse Foundation, Inc. nor the
25
names of its contributors may be used to endorse or promote
26
products derived from this software without specific prior
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
using System.Collections.Generic;
47
using NGit.Storage.Pack;
51
namespace NGit.Storage.Pack
53
internal class BaseSearch
55
private static readonly int M_BLOB = FileMode.REGULAR_FILE.GetBits();
57
private static readonly int M_TREE = FileMode.TREE.GetBits();
59
private readonly ProgressMonitor progress;
61
private readonly ObjectReader reader;
63
private readonly ObjectId[] baseTrees;
65
private readonly ObjectIdOwnerMap<ObjectToPack> objectsMap;
67
private readonly IList<ObjectToPack> edgeObjects;
69
private readonly IntSet alreadyProcessed;
71
private readonly ObjectIdOwnerMap<BaseSearch.TreeWithData> treeCache;
73
private readonly CanonicalTreeParser parser;
75
private readonly MutableObjectId idBuf;
77
internal BaseSearch(ProgressMonitor countingMonitor, ICollection<RevTree> bases,
78
ObjectIdOwnerMap<ObjectToPack> objects, IList<ObjectToPack> edges, ObjectReader
81
progress = countingMonitor;
83
baseTrees = Sharpen.Collections.ToArray(bases, new ObjectId[bases.Count]);
86
alreadyProcessed = new IntSet();
87
treeCache = new ObjectIdOwnerMap<BaseSearch.TreeWithData>();
88
parser = new CanonicalTreeParser();
89
idBuf = new MutableObjectId();
92
/// <exception cref="System.IO.IOException"></exception>
93
internal virtual void AddBase(int objectType, byte[] pathBuf, int pathLen, int pathHash
96
int tailMode = ModeForType(objectType);
101
if (!alreadyProcessed.Add(pathHash))
107
foreach (ObjectId root in baseTrees)
109
Add(root, Constants.OBJ_TREE, pathHash);
113
int firstSlash = NextSlash(pathBuf, 0, pathLen);
114
foreach (ObjectId root_1 in baseTrees)
117
int end = firstSlash;
118
int mode = end != pathLen ? M_TREE : tailMode;
119
parser.Reset(ReadTree(root_1));
122
int cmp = parser.PathCompare(pathBuf, ptr, end, mode);
134
if (parser.EntryFileMode.GetObjectType() == objectType)
136
idBuf.FromRaw(parser.IdBuffer, parser.IdOffset);
137
Add(idBuf, objectType, pathHash);
141
if (!FileMode.TREE.Equals(parser.EntryRawMode))
146
end = NextSlash(pathBuf, ptr, pathLen);
147
mode = end != pathLen ? M_TREE : tailMode;
148
idBuf.FromRaw(parser.IdBuffer, parser.IdOffset);
149
parser.Reset(ReadTree(idBuf));
155
private static int ModeForType(int typeCode)
159
case Constants.OBJ_TREE:
164
case Constants.OBJ_BLOB:
177
private static int NextSlash(byte[] pathBuf, int ptr, int end)
179
while (ptr < end && pathBuf[ptr] != '/')
186
private void Add(AnyObjectId id, int objectType, int pathHash)
188
ObjectToPack obj = new ObjectToPack(id, objectType);
190
obj.SetPathHash(pathHash);
191
if (objectsMap.AddIfAbsent(obj) == obj)
193
edgeObjects.AddItem(obj);
198
/// <exception cref="NGit.Errors.MissingObjectException"></exception>
199
/// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception>
200
/// <exception cref="System.IO.IOException"></exception>
201
private byte[] ReadTree(AnyObjectId id)
203
BaseSearch.TreeWithData tree = treeCache.Get(id);
208
ObjectLoader ldr = reader.Open(id, Constants.OBJ_TREE);
209
byte[] buf = ldr.GetCachedBytes(int.MaxValue);
210
treeCache.Add(new BaseSearch.TreeWithData(id, buf));
214
[System.Serializable]
215
private class TreeWithData : ObjectIdOwnerMap.Entry
217
internal readonly byte[] buf;
219
internal TreeWithData(AnyObjectId id, byte[] buf) : base(id)