} else if (remotes.size() == 0) {
// If no remotes are specified, default to the origin remote
addRemote("origin");
}
final ProgressListener progressListener = getProgressListener();
progressListener.started();
Optional<Integer> repoDepth = repository().getDepth();
if (repoDepth.isPresent()) {
if (fullDepth) {
depth = Optional.of(Integer.MAX_VALUE);
}
if (depth.isPresent()) {
if (depth.get() > repoDepth.get()) {
command(ConfigOp.class).setAction(ConfigAction.CONFIG_SET)
.setScope(ConfigScope.LOCAL).setName(Repository.DEPTH_CONFIG_KEY)
.setValue(depth.get().toString()).call();
repoDepth = depth;
}
}
} else if (depth.isPresent() || fullDepth) {
// Ignore depth, this is a full repository
depth = Optional.absent();
fullDepth = false;
}
TransferSummary result = new TransferSummary();
for (Remote remote : remotes) {
final ImmutableSet<Ref> remoteRemoteRefs = command(LsRemote.class)
.setRemote(Suppliers.ofInstance(Optional.of(remote)))
.retrieveTags(!remote.getMapped() && (!repoDepth.isPresent() || fullDepth))
.call();
final ImmutableSet<Ref> localRemoteRefs = command(LsRemote.class)
.retrieveLocalRefs(true).setRemote(Suppliers.ofInstance(Optional.of(remote)))
.call();
// If we have specified a depth to pull, we may have more history to pull from existing
// refs.
List<ChangedRef> needUpdate = findOutdatedRefs(remote, remoteRemoteRefs,
localRemoteRefs, depth);
if (prune) {
// Delete local refs that aren't in the remote
List<Ref> locals = new ArrayList<Ref>();
// only branches, not tags, appear in the remoteRemoteRefs list so we will not catch
// any tags in this check. However, we do not track which remote originally
// provided a tag so it makes sense not to prune them anyway.
for (Ref remoteRef : remoteRemoteRefs) {
Optional<Ref> localRef = findLocal(remoteRef, localRemoteRefs);
if (localRef.isPresent()) {
locals.add(localRef.get());
}
}
for (Ref localRef : localRemoteRefs) {
if (!locals.contains(localRef)) {
// Delete the ref
ChangedRef changedRef = new ChangedRef(localRef, null,
ChangeTypes.REMOVED_REF);
needUpdate.add(changedRef);
command(UpdateRef.class).setDelete(true).setName(localRef.getName()).call();
}
}
}
Optional<IRemoteRepo> remoteRepo = getRemoteRepo(remote, repository()
.deduplicationService());
Preconditions.checkState(remoteRepo.isPresent(), "Failed to connect to the remote.");
IRemoteRepo remoteRepoInstance = remoteRepo.get();
try {
remoteRepoInstance.open();
} catch (IOException e) {
Throwables.propagate(e);
}
try {
int refCount = 0;
for (ChangedRef ref : needUpdate) {
if (ref.getType() != ChangeTypes.REMOVED_REF) {
refCount++;
Optional<Integer> newFetchLimit = depth;
// If we haven't specified a depth, but this is a shallow repository, set
// the
// fetch limit to the current repository depth.
if (!newFetchLimit.isPresent() && repoDepth.isPresent()
&& ref.getType() == ChangeTypes.ADDED_REF) {
newFetchLimit = repoDepth;
}
// Fetch updated data from this ref
Ref newRef = ref.getNewRef();
remoteRepoInstance.fetchNewData(newRef, newFetchLimit, progressListener);
if (repoDepth.isPresent() && !fullDepth) {
// Update the repository depth if it is deeper than before.
int newDepth;
try {
newDepth = repository().graphDatabase().getDepth(
newRef.getObjectId());
} catch (IllegalStateException e) {
throw new RuntimeException(ref.toString(), e);
}
if (newDepth > repoDepth.get()) {
command(ConfigOp.class).setAction(ConfigAction.CONFIG_SET)
.setScope(ConfigScope.LOCAL)
.setName(Repository.DEPTH_CONFIG_KEY)
.setValue(Integer.toString(newDepth)).call();
repoDepth = Optional.of(newDepth);
}
}
// Update the ref
Ref updatedRef = updateLocalRef(newRef, remote, localRemoteRefs);
ref.setNewRef(updatedRef);
}
}
if (needUpdate.size() > 0) {
result.addAll(remote.getFetchURL(), needUpdate);
}
// Update HEAD ref
if (!remote.getMapped()) {
Ref remoteHead = remoteRepoInstance.headRef();
if (remoteHead != null) {
updateLocalRef(remoteHead, remote, localRemoteRefs);
}
}
} finally {
try {
remoteRepoInstance.close();
} catch (IOException e) {
Throwables.propagate(e);
}
}
}
if (fullDepth) {
// The full history was fetched, this is no longer a shallow clone
command(ConfigOp.class).setAction(ConfigAction.CONFIG_UNSET)
.setScope(ConfigScope.LOCAL).setName(Repository.DEPTH_CONFIG_KEY).call();
}
progressListener.complete();
return result;
}