Package org.locationtech.geogig.api.porcelain

Source Code of org.locationtech.geogig.api.porcelain.CloneOp

/* 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.porcelain;

import java.io.IOException;

import javax.annotation.Nullable;

import org.locationtech.geogig.api.AbstractGeoGigOp;
import org.locationtech.geogig.api.GlobalContextBuilder;
import org.locationtech.geogig.api.ProgressListener;
import org.locationtech.geogig.api.Ref;
import org.locationtech.geogig.api.Remote;
import org.locationtech.geogig.api.SymRef;
import org.locationtech.geogig.api.plumbing.LsRemote;
import org.locationtech.geogig.api.plumbing.RefParse;
import org.locationtech.geogig.api.plumbing.UpdateRef;
import org.locationtech.geogig.api.porcelain.ConfigOp.ConfigAction;
import org.locationtech.geogig.api.porcelain.ConfigOp.ConfigScope;
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 com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;

/**
* Clones a remote repository to a given directory.
*
*/
public class CloneOp extends AbstractGeoGigOp<Void> {

    private Optional<String> branch = Optional.absent();

    private String repositoryURL;

    private String username = null;

    private String password = null;

    private Optional<Integer> depth = Optional.absent();

    /**
     * @param repositoryURL the URL of the repository to clone
     * @return {@code this}
     */
    public CloneOp setRepositoryURL(final String repositoryURL) {
        this.repositoryURL = repositoryURL;
        return this;
    }

    /**
     * Get the repository URL to be cloned
     */
    public Optional<String> getRepositoryURL() {
        return Optional.fromNullable(repositoryURL);
    }

    /**
     * @param username user name for the repository
     * @return {@code this}
     */
    public CloneOp setUserName(String username) {
        this.username = username;
        return this;
    }

    /**
     * @param password password for the repository
     * @return {@code this}
     */
    public CloneOp setPassword(String password) {
        this.password = password;
        return this;
    }

    /**
     * @param branch the branch to checkout when the clone is complete
     * @return {@code this}
     */
    public CloneOp setBranch(@Nullable String branch) {
        this.branch = Optional.fromNullable(branch);
        return this;
    }

    public Optional<String> getBranch() {
        return branch;
    }

    /**
     * @param depth the depth of the clone, if depth is < 1, then a full clone s performed
     * @return {@code this}
     */
    public CloneOp setDepth(final int depth) {
        if (depth > 0) {
            this.depth = Optional.of(depth);
        }
        return this;
    }

    public Optional<Integer> getDepth() {
        return depth;
    }

    /**
     * Executes the clone operation.
     *
     * @return {@code null}
     * @see org.locationtech.geogig.api.AbstractGeoGigOp#call()
     */
    @Override
    protected Void _call() {
        Preconditions.checkArgument(repositoryURL != null && !repositoryURL.isEmpty(),
                "No repository specified to clone from.");
        Repository repository = repository();
        if (repository.isSparse()) {
            Preconditions
                    .checkArgument(branch.isPresent(), "No branch specified for sparse clone.");
        }

        ProgressListener progressListener = getProgressListener();
        progressListener.started();

        // Set up origin
        Remote remote = command(RemoteAddOp.class).setName("origin").setURL(repositoryURL)
                .setMapped(repository.isSparse()).setUserName(username).setPassword(password)
                .setBranch(repository.isSparse() ? branch.get() : null).call();

        if (!depth.isPresent()) {
            // See if we are cloning a shallow clone. If so, a depth must be specified.
            Optional<IRemoteRepo> remoteRepo = RemoteUtils.newRemote(
                    GlobalContextBuilder.builder.build(Hints.readOnly()), remote, repository,
                    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 {
                depth = remoteRepoInstance.getDepth();
            } finally {
                try {
                    remoteRepoInstance.close();
                } catch (IOException e) {
                    Throwables.propagate(e);
                }
            }
        }

        if (depth.isPresent()) {
            command(ConfigOp.class).setAction(ConfigAction.CONFIG_SET).setScope(ConfigScope.LOCAL)
                    .setName(Repository.DEPTH_CONFIG_KEY).setValue(depth.get().toString()).call();
        }

        // Fetch remote data
        command(FetchOp.class).setDepth(depth.or(0)).setProgressListener(progressListener).call();

        // Set up remote tracking branches
        final ImmutableSet<Ref> remoteRefs = command(LsRemote.class).retrieveTags(false)
                .setRemote(Suppliers.ofInstance(Optional.of(remote))).call();

        boolean emptyRepo = true;

        for (Ref remoteRef : remoteRefs) {
            if (emptyRepo && !remoteRef.getObjectId().isNull()) {
                emptyRepo = false;
            }
            String branchName = remoteRef.localName();
            if (remoteRef instanceof SymRef) {
                continue;
            }
            if (!command(RefParse.class).setName(Ref.HEADS_PREFIX + branchName).call().isPresent()) {
                command(BranchCreateOp.class).setName(branchName)
                        .setSource(remoteRef.getObjectId().toString()).call();
            } else {
                command(UpdateRef.class).setName(Ref.HEADS_PREFIX + branchName)
                        .setNewValue(remoteRef.getObjectId()).call();
            }

            command(ConfigOp.class).setAction(ConfigAction.CONFIG_SET).setScope(ConfigScope.LOCAL)
                    .setName("branches." + branchName + ".remote").setValue(remote.getName())
                    .call();

            command(ConfigOp.class).setAction(ConfigAction.CONFIG_SET).setScope(ConfigScope.LOCAL)
                    .setName("branches." + branchName + ".merge")
                    .setValue(Ref.HEADS_PREFIX + remoteRef.localName()).call();
        }

        if (!emptyRepo) {
            // checkout branch
            if (branch.isPresent()) {
                command(CheckoutOp.class).setForce(true).setSource(branch.get()).call();
            } else {
                // checkout the head
                final Optional<Ref> currRemoteHead = command(RefParse.class).setName(
                        Ref.REMOTES_PREFIX + remote.getName() + "/" + Ref.HEAD).call();
                if (currRemoteHead.isPresent() && currRemoteHead.get() instanceof SymRef) {
                    final SymRef remoteHeadRef = (SymRef) currRemoteHead.get();
                    final String currentBranch = Ref.localName(remoteHeadRef.getTarget());
                    command(CheckoutOp.class).setForce(true).setSource(currentBranch).call();
                } else {
                    // just leave at default; should be master since we just initialized the repo.
                }

            }
        }

        progressListener.complete();

        return null;
    }
}
TOP

Related Classes of org.locationtech.geogig.api.porcelain.CloneOp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.