org.locationtech.geogig.remotes.LsRemoteOp.java Source code

Java tutorial

Introduction

Here is the source code for org.locationtech.geogig.remotes.LsRemoteOp.java

Source

/* Copyright (c) 2012-2017 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.remotes;

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Set;
import java.util.stream.Collectors;

import org.locationtech.geogig.model.Ref;
import org.locationtech.geogig.plumbing.ForEachRef;
import org.locationtech.geogig.remotes.internal.IRemoteRepo;
import org.locationtech.geogig.repository.AbstractGeoGigOp;
import org.locationtech.geogig.repository.Remote;

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.collect.ImmutableSet;
import com.google.common.collect.Sets;

/**
 * Connects to the specified remote, retrieves its {@link Ref refs}, closes the remote connection
 * and returns the list of remote references.
 */
public class LsRemoteOp extends AbstractGeoGigOp<ImmutableSet<Ref>> {

    // optional, if not supplied #remoteRepo is mandatory
    private Supplier<Optional<Remote>> remote;

    // optional, if not supplied #remote is mandatory, if supplied #local must be false
    private IRemoteRepo remoteRepo;

    private boolean getHead = false;

    private boolean getBranches = true;

    private boolean getTags = true;

    private boolean local = false;

    /**
     * Constructs a new {@code LsRemote}.
     */
    public LsRemoteOp() {
        this.remote = Suppliers.ofInstance(Optional.absent());
        this.getBranches = true;
        this.getTags = true;
    }

    /**
     * @param remote the remote whose refs should be listed
     * @return {@code this}
     */
    public LsRemoteOp setRemote(Supplier<Optional<Remote>> remote) {
        this.remote = remote;
        this.remoteRepo = null;
        return this;
    }

    public LsRemoteOp setRemote(Remote remote) {
        this.remote = Suppliers.ofInstance(Optional.of(remote));
        this.remoteRepo = null;
        return this;
    }

    public LsRemoteOp setRemote(IRemoteRepo remoteRepo) {
        this.remoteRepo = remoteRepo;
        this.remote = () -> Optional.of(remoteRepo.getInfo());
        return this;
    }

    /**
     * Find the remote to be listed
     */
    public Optional<Remote> getRemote() {
        return remote.get();
    }

    /**
     * @param getHeads tells whether to retrieve remote heads (i.e. branches), defaults to
     *        {@code true}
     * @return {@code this}
     */
    public LsRemoteOp retrieveBranches(boolean getHeads) {
        this.getBranches = getHeads;
        return this;
    }

    /**
     * @param getTags tells whether to retrieve remote tags, defaults to {@code true}
     * @return {@code this}
     */
    public LsRemoteOp 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 LsRemoteOp retrieveLocalRefs(boolean local) {
        this.local = local;
        return this;
    }

    /**
     * Whether to retrieve the remote's {@link Ref#HEAD HEAD} ref, deaults to {@code false}
     */
    public LsRemoteOp retrieveHead(boolean getHead) {
        this.getHead = getHead;
        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() {
        final Remote remoteConfig = this.remote.get().orNull();

        Preconditions.checkState(remoteRepo != null || remoteConfig != null, "Remote was not provided");

        if (local) {
            checkArgument(remoteConfig != null, "if retrieving local remote refs, a Remote must be provided");
            return locallyKnownRefs(remoteConfig);
        }

        ImmutableSet<Ref> remoteRefs;
        IRemoteRepo remoteRepo = this.remoteRepo;
        final boolean closeRemote = remoteRepo == null;
        if (remoteRepo == null) {
            remoteRepo = openRemote(remoteConfig);
            getProgressListener()
                    .setDescription("Connected to remote " + remoteConfig.getName() + ". Retrieving references");
        }

        Optional<Ref> headRef = Optional.absent();
        try {
            remoteRefs = remoteRepo.listRefs(repository(), getBranches, getTags);
            if (getHead) {
                headRef = remoteRepo.headRef();
            }
        } finally {
            if (closeRemote) {
                remoteRepo.close();
            }
        }

        if (headRef.isPresent()) {
            Set<Ref> refs = Sets.newHashSet(remoteRefs);
            refs.add(headRef.get());
            remoteRefs = ImmutableSet.copyOf(refs);
        }

        Set<Ref> filtered = remoteRefs.stream().filter(r -> remoteConfig.mapToLocal(r.getName()).isPresent())
                .collect(Collectors.toSet());

        return ImmutableSet.copyOf(filtered);

    }

    private IRemoteRepo openRemote(Remote remote) {
        return command(OpenRemote.class).setRemote(remote).readOnly().call();
    }

    /**
     * @see ForEachRef
     */
    private ImmutableSet<Ref> locallyKnownRefs(final Remote remoteConfig) {

        Predicate<Ref> filter = input -> {
            java.util.Optional<String> remoteRef = remoteConfig.mapToRemote(input.getName());
            return remoteRef.isPresent();
        };
        return command(ForEachRef.class).setFilter(filter).call();
    }

}