/* Copyright (c) 2012-2013 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.cli.porcelain;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import jline.console.ConsoleReader;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Color;
import org.locationtech.geogig.api.GeoGIG;
import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.RevCommit;
import org.locationtech.geogig.api.RevObject.TYPE;
import org.locationtech.geogig.api.plumbing.ParseTimestamp;
import org.locationtech.geogig.api.plumbing.ResolveObjectType;
import org.locationtech.geogig.api.plumbing.RevParse;
import org.locationtech.geogig.api.plumbing.diff.DiffEntry;
import org.locationtech.geogig.api.plumbing.merge.ReadMergeCommitMessageOp;
import org.locationtech.geogig.api.porcelain.CommitOp;
import org.locationtech.geogig.api.porcelain.DiffOp;
import org.locationtech.geogig.api.porcelain.NothingToCommitException;
import org.locationtech.geogig.cli.AbstractCommand;
import org.locationtech.geogig.cli.CLICommand;
import org.locationtech.geogig.cli.CommandFailedException;
import org.locationtech.geogig.cli.GeogigCLI;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
/**
* Stores the current contents of the index in a new commit along with a log message from the user
* describing the changes.
* <p>
* CLI proxy for {@link CommitOp}
* <p>
* Usage:
* <ul>
* <li> {@code geogig commit -m <msg>}
* </ul>
*
* @see CommitOp
*/
@Parameters(commandNames = "commit", commandDescription = "Record staged changes to the repository")
public class Commit extends AbstractCommand implements CLICommand {
@Parameter(names = "-m", description = "Commit message")
private String message;
@Parameter(names = "-c", description = "Commit to reuse")
private String commitToReuse;
@Parameter(names = "-t", description = "Commit timestamp")
private String commitTimestamp;
@Parameter(names = "--amend", description = "Amends last commit")
private boolean amend;
@Parameter(description = "<pathFilter> [<paths_to_commit]...")
private List<String> pathFilters = Lists.newLinkedList();
/**
* Executes the commit command using the provided options.
*
* @param cli
* @see org.locationtech.geogig.cli.AbstractCommand#runInternal(org.locationtech.geogig.cli.GeogigCLI)
*/
@Override
public void runInternal(GeogigCLI cli) throws IOException {
final GeoGIG geogig = cli.getGeogig();
if (message == null || Strings.isNullOrEmpty(message)) {
message = geogig.command(ReadMergeCommitMessageOp.class).call();
}
checkParameter(!Strings.isNullOrEmpty(message) || commitToReuse != null || amend,
"No commit message provided");
ConsoleReader console = cli.getConsole();
Ansi ansi = newAnsi(console.getTerminal());
RevCommit commit;
try {
CommitOp commitOp = geogig.command(CommitOp.class).setMessage(message).setAmend(amend);
if (commitTimestamp != null && !Strings.isNullOrEmpty(commitTimestamp)) {
Long millis = geogig.command(ParseTimestamp.class).setString(commitTimestamp)
.call();
commitOp.setCommitterTimestamp(millis.longValue());
}
if (commitToReuse != null) {
Optional<ObjectId> commitId = geogig.command(RevParse.class)
.setRefSpec(commitToReuse).call();
checkParameter(commitId.isPresent(), "Provided reference does not exist");
TYPE type = geogig.command(ResolveObjectType.class).setObjectId(commitId.get())
.call();
checkParameter(TYPE.COMMIT.equals(type),
"Provided reference does not resolve to a commit");
commitOp.setCommit(geogig.getRepository().getCommit(commitId.get()));
}
commit = commitOp.setPathFilters(pathFilters)
.setProgressListener(cli.getProgressListener()).call();
} catch (NothingToCommitException noChanges) {
throw new CommandFailedException(noChanges.getMessage(), noChanges);
}
final ObjectId parentId = commit.parentN(0).or(ObjectId.NULL);
console.println("[" + commit.getId() + "] " + commit.getMessage());
console.print("Committed, counting objects...");
Iterator<DiffEntry> diff = geogig.command(DiffOp.class).setOldVersion(parentId)
.setNewVersion(commit.getId()).call();
int adds = 0, deletes = 0, changes = 0;
DiffEntry diffEntry;
while (diff.hasNext()) {
diffEntry = diff.next();
switch (diffEntry.changeType()) {
case ADDED:
++adds;
break;
case REMOVED:
++deletes;
break;
case MODIFIED:
++changes;
break;
}
}
ansi.fg(Color.GREEN).a(adds).reset().a(" features added, ").fg(Color.YELLOW).a(changes)
.reset().a(" changed, ").fg(Color.RED).a(deletes).reset().a(" deleted.").reset()
.newline();
console.print(ansi.toString());
}
}