/* Copyright (c) 2012-2014 Boundless and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/edl-v10.html * * Contributors: * Gabriel Roldan (Boundless) - initial implementation */ package org.locationtech.geogig.api.plumbing; import java.io.IOException; import org.locationtech.geogig.api.AbstractGeoGigOp; import org.locationtech.geogig.api.GlobalContextBuilder; import org.locationtech.geogig.api.Ref; import org.locationtech.geogig.api.Remote; import org.locationtech.geogig.remote.IRemoteRepo; import org.locationtech.geogig.remote.RemoteUtils; import org.locationtech.geogig.repository.Hints; import org.locationtech.geogig.repository.Repository; import org.locationtech.geogig.storage.DeduplicationService; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableSet; /** * Connects to the specified remote, retrieves its {@link Ref refs}, closes the remote connection * and returns the list of remote references. */ public class LsRemote extends AbstractGeoGigOp<ImmutableSet<Ref>> { private Supplier<Optional<Remote>> remote; private boolean getHeads; private boolean getTags; private boolean local; /** * Constructs a new {@code LsRemote}. */ public LsRemote() { Optional<Remote> abstent = Optional.absent(); this.remote = Suppliers.ofInstance(abstent); this.getHeads = true; this.getTags = true; } /** * @param remote the remote whose refs should be listed * @return {@code this} */ public LsRemote setRemote(Supplier<Optional<Remote>> remote) { this.remote = remote; return this; } /** * Find the remote to be listed */ public Optional<Remote> getRemote() { return remote.get(); } /** * @param getHeads tells whether to retrieve remote heads, defaults to {@code true} * @return {@code this} */ public LsRemote retrieveHeads(boolean getHeads) { this.getHeads = getHeads; return this; } /** * @param getTags tells whether to retrieve remote tags, defaults to {@code true} * @return {@code this} */ public LsRemote retrieveTags(boolean getTags) { this.getTags = getTags; return this; } /** * @param local if {@code true} retrieves the refs of the remote repository known to the local * repository instead (i.e. those under the {@code refs/remotes/<remote name>} namespace * in the local repo. Defaults to {@code false} * @return {@code this} */ public LsRemote retrieveLocalRefs(boolean local) { this.local = local; return this; } /** * Lists all refs for the given remote. * * @return an immutable set of the refs for the given remote */ @Override protected ImmutableSet<Ref> _call() { Preconditions.checkState(remote.get().isPresent(), "Remote was not provided"); final Remote remoteConfig = remote.get().get(); if (local) { return locallyKnownRefs(remoteConfig); } getProgressListener().setDescription("Obtaining remote " + remoteConfig.getName()); Optional<IRemoteRepo> remoteRepo = getRemoteRepo(remoteConfig); Preconditions.checkState(remoteRepo.isPresent(), "Remote could not be opened."); getProgressListener().setDescription("Connecting to remote " + remoteConfig.getName()); try { remoteRepo.get().open(); } catch (IOException e) { throw Throwables.propagate(e); } getProgressListener().setDescription( "Connected to remote " + remoteConfig.getName() + ". Retrieving references"); ImmutableSet<Ref> remoteRefs; try { remoteRefs = remoteRepo.get().listRefs(getHeads, getTags); } finally { try { remoteRepo.get().close(); } catch (IOException e) { throw Throwables.propagate(e); } } return remoteRefs; } /** * @param remote the remote to get * @return an interface for the remote repository */ public Optional<IRemoteRepo> getRemoteRepo(Remote remote) { Repository localRepository = repository(); DeduplicationService deduplicationService = context.deduplicationService(); return RemoteUtils.newRemote(GlobalContextBuilder.builder.build(Hints.readOnly()), remote, localRepository, deduplicationService); } /** * @see ForEachRef */ private ImmutableSet<Ref> locallyKnownRefs(final Remote remoteConfig) { Predicate<Ref> filter = new Predicate<Ref>() { final String prefix = Ref.REMOTES_PREFIX + remoteConfig.getName() + "/"; @Override public boolean apply(Ref input) { return input.getName().startsWith(prefix); } }; return command(ForEachRef.class).setFilter(filter).call(); } }