Browse Source

Merge 6a65c9a7de into 1e391d47ba

pull/55/merge
Kenneth Endfinger 2 years ago
parent
commit
26a11565ac
No account linked to committer's email address

+ 1
- 0
org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin View File

@@ -28,6 +28,7 @@ org.eclipse.jgit.pgm.Push
org.eclipse.jgit.pgm.ReceivePack
org.eclipse.jgit.pgm.Reflog
org.eclipse.jgit.pgm.Remote
org.eclipse.jgit.pgm.RemoteHelper
org.eclipse.jgit.pgm.Repo
org.eclipse.jgit.pgm.Reset
org.eclipse.jgit.pgm.RevList

+ 1
- 0
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties View File

@@ -270,6 +270,7 @@ usage_PrunePreserved=Remove the preserved subdirectory containing previously pre
usage_ReadDirCache= Read the DirCache 100 times
usage_RebuildCommitGraph=Recreate a repository from another one's commit graph
usage_Remote=Manage set of tracked repositories
usage_RemoteHelper=Helper for using JGit with Git
usage_RepositoryToReadFrom=Repository to read from
usage_RepositoryToReceiveInto=Repository to receive into
usage_RevList=List commit objects in reverse chronological order

+ 109
- 0
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RemoteHelper.java View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
* Copyright (C) 2008, Google Inc.
* Copyright (C) 2010, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2010, Sasa Zivkov <sasa.zivkov@sap.com>
* Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
* Copyright (C) 2016, Rüdiger Herrmann <ruediger.herrmann@gmx.de>
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.pgm;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.integrate.remotehelper.RemoteHelperDriver;
import org.eclipse.jgit.integrate.remotehelper.internal.RemoteHelperMain;
import org.eclipse.jgit.integrate.remotehelper.internal.RemoteHelperTransport;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.URIish;
import org.kohsuke.args4j.Argument;

import java.io.*;

@Command(common = true, name = "remote-helper", usage = "usage_RemoteHelper")
class RemoteHelper extends TextBuiltin {
@Argument(index = 0, metaVar = "metaVar_remoteName")
private String remote;

@Argument(index = 1, metaVar = "metaVar_url")
private String url;

@Override
protected final boolean requiresRepository() {
return false;
}

@Override
protected void run() throws Exception {
String realUrl = url == null ? remote : url;
String realRemote = url == null ? "" : remote;

String dir = gitdir;
if (dir == null) {
dir = System.getenv("GIT_DIR");
}

if (dir == null) {
dir = ".";
}

Repository repository = Git.open(new File(dir)).getRepository();
init(repository, null);

RemoteHelperDriver driver = new RemoteHelperDriver(
repository,
new URIish(realUrl),
realRemote,
new PrintWriter(outw),
new TextProgressMonitor(errw)
);

driver.setProvider(new RemoteHelperTransport(driver));

BufferedReader reader = new BufferedReader(new InputStreamReader(ins));

String line;
while ((line = reader.readLine()) != null) {
driver.handleLine(line);
}
}
}

+ 36
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/RemoteHelperCapability.java View File

@@ -0,0 +1,36 @@
package org.eclipse.jgit.integrate.remotehelper;

public class RemoteHelperCapability {
public static final RemoteHelperCapability CONNECT = new RemoteHelperCapability("connect");
public static final RemoteHelperCapability PUSH = new RemoteHelperCapability("push");
public static final RemoteHelperCapability EXPORT = new RemoteHelperCapability("export");
public static final RemoteHelperCapability FETCH = new RemoteHelperCapability("fetch");
public static final RemoteHelperCapability IMPORT = new RemoteHelperCapability("import");
public static final RemoteHelperCapability OPTION = new RemoteHelperCapability("option");
public static final RemoteHelperCapability BIDI_IMPORT = new RemoteHelperCapability("bidi-import");


private final String name;
private final String data;

public RemoteHelperCapability(String name) {
this(name, null);
}

public RemoteHelperCapability(String name, String data) {
this.name = name;
this.data = data;
}

public String getName() {
return name;
}

public String getData() {
return data;
}

public boolean hasData() {
return data != null;
}
}

+ 25
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/RemoteHelperCommand.java View File

@@ -0,0 +1,25 @@
package org.eclipse.jgit.integrate.remotehelper;

import java.util.List;

public abstract class RemoteHelperCommand {
private final RemoteHelperContext context;

public RemoteHelperCommand(RemoteHelperContext context) {
this.context = context;
}

public boolean isBatched() {
return false;
}

public abstract void handle(
List<String> arguments
) throws Exception;

public void complete() throws Exception {}

public RemoteHelperContext getContext() {
return context;
}
}

+ 22
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/RemoteHelperContext.java View File

@@ -0,0 +1,22 @@
package org.eclipse.jgit.integrate.remotehelper;

import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.URIish;

public interface RemoteHelperContext {
void reply(String data);
void complete();

Repository getRepository();

String getRemoteName();
URIish getUrl();

RemoteHelperProvider getProvider();
void setProvider(RemoteHelperProvider provider);

ProgressMonitor getProgressMonitor();

void close();
}

+ 152
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/RemoteHelperDriver.java View File

@@ -0,0 +1,152 @@
package org.eclipse.jgit.integrate.remotehelper;

import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.URIish;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class RemoteHelperDriver implements RemoteHelperContext {
private final Repository repository;
private final URIish uri;
private final PrintWriter out;
private final String remoteName;
private final ProgressMonitor monitor;

private RemoteHelperProvider provider;

public RemoteHelperDriver(Repository repository, URIish uri, String remoteName, PrintWriter out, ProgressMonitor monitor) {
this.repository = repository;
this.uri = uri;
this.remoteName = remoteName;
this.out = out;
this.monitor = monitor;
}

@Override
public void reply(String data) {
out.println(data);
out.flush();
}

@Override
public void complete() {
out.println();
out.flush();
}

@Override
public Repository getRepository() {
return repository;
}

@Override
public String getRemoteName() {
return remoteName;
}

@Override
public URIish getUrl() {
return uri;
}

@Override
public RemoteHelperProvider getProvider() {
return provider;
}

@Override
public void setProvider(RemoteHelperProvider provider) {
this.provider = provider;
}

@Override
public ProgressMonitor getProgressMonitor() {
return monitor;
}

@Override
public void close() {
if (provider != null) {
getProvider().close();
}
}

private RemoteHelperCommand lastCommand;

public void handleLine(String line) throws Exception {
if (provider == null) {
throw new IllegalStateException("Remote Helper Provider was not set.");
}

line = line.trim();

if (line.isEmpty()) {
if (lastCommand != null) {
lastCommand.complete();
lastCommand = null;
}

return;
}

List<String> parts = Arrays.asList(line.split(" "));
String commandName = parts.get(0);
List<String> arguments;

if (parts.size() > 1) {
arguments = parts.subList(1, parts.size());
} else {
arguments = Collections.emptyList();
}

RemoteHelperCommand command = getProvider().getCommand(commandName);
if (command == null) {
command = getDefaultCommand(commandName);
}

if (command == null) {
throw new IllegalArgumentException("Unknown Command: " + line);
}

command.handle(arguments);

if (!command.isBatched()) {
command.complete();
} else {
lastCommand = command;
}
}

public RemoteHelperCommand getDefaultCommand(String name) {
if ("capabilities".equals(name)) {
return new DefaultCapabilitiesCommand(this);
}
return null;
}

private class DefaultCapabilitiesCommand extends RemoteHelperCommand {
public DefaultCapabilitiesCommand(RemoteHelperContext context) {
super(context);
}

@Override
public void handle(List<String> arguments) throws Exception {
for (RemoteHelperCapability capability : getProvider().getCapabilities()) {
String line = capability.getName();
if (capability.hasData()) {
line += " " + capability.getData();
}

getContext().reply(line);
}

getContext().complete();
}
}
}

+ 22
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/RemoteHelperProvider.java View File

@@ -0,0 +1,22 @@
package org.eclipse.jgit.integrate.remotehelper;

import java.util.Collection;

public abstract class RemoteHelperProvider {
private final RemoteHelperContext context;

public RemoteHelperProvider(RemoteHelperContext context) {
this.context = context;

context.setProvider(this);
}

public abstract RemoteHelperCommand getCommand(String name);
public abstract Collection<RemoteHelperCapability> getCapabilities();

public RemoteHelperContext getContext() {
return context;
}

public abstract void close();
}

+ 46
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/internal/RemoteHelperMain.java View File

@@ -0,0 +1,46 @@
package org.eclipse.jgit.integrate.remotehelper.internal;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.integrate.remotehelper.RemoteHelperDriver;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.URIish;

import java.io.*;

public class RemoteHelperMain {
public static void main(String[] args) throws Exception {
main(args, System.getenv("GIT_DIR"));
}

public static void main(String[] args, String gitDir) throws Exception {
if (args.length < 1 || args.length > 2) {
System.err.println("Usage: remote-helper <remote/url> [url]");
System.exit(1);
}

String remoteName = args.length == 2 ? args[0] : "";
String url = args.length == 2 ? args[1] : args[0];

if (gitDir == null) {
System.err.println("ERROR: GIT_DIR was not specified.");
System.exit(1);
}

RemoteHelperDriver driver = new RemoteHelperDriver(
Git.open(new File(gitDir)).getRepository(),
new URIish(url),
remoteName,
new PrintWriter(System.out),
new TextProgressMonitor()
);

driver.setProvider(new RemoteHelperTransport(driver));

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

String line;
while ((line = reader.readLine()) != null) {
driver.handleLine(line);
}
}
}

+ 97
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/internal/RemoteHelperTransport.java View File

@@ -0,0 +1,97 @@
package org.eclipse.jgit.integrate.remotehelper.internal;

import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.integrate.remotehelper.RemoteHelperCapability;
import org.eclipse.jgit.integrate.remotehelper.RemoteHelperCommand;
import org.eclipse.jgit.integrate.remotehelper.RemoteHelperContext;
import org.eclipse.jgit.integrate.remotehelper.RemoteHelperProvider;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.PushConnection;
import org.eclipse.jgit.transport.Transport;

import java.util.ArrayList;
import java.util.Collection;

public class RemoteHelperTransport extends RemoteHelperProvider {
private Transport transport;

public RemoteHelperTransport(RemoteHelperContext context) {
super(context);

Transport transport;
try {
transport = Transport.open(context.getRepository(), context.getUrl());
} catch (Exception e) {
throw new RuntimeException(e);
}
setTransport(transport);
}

@Override
public RemoteHelperCommand getCommand(String name) {
if ("fetch".equals(name)) {
return new TransportFetchCommand(this);
} else if ("list".equals(name)) {
return new TransportListCommand(this);
} else if ("push".equals(name)) {
return new TransportPushCommand(this);
}
return null;
}

@Override
public Collection<RemoteHelperCapability> getCapabilities() {
ArrayList<RemoteHelperCapability> capabilities = new ArrayList<>();

try {
FetchConnection fetchConnection = getFetchConnection();
PushConnection pushConnection = getPushConnection();
if (fetchConnection != null) {
fetchConnection.close();
capabilities.add(RemoteHelperCapability.FETCH);
}

if (pushConnection != null) {
pushConnection.close();
capabilities.add(RemoteHelperCapability.PUSH);
}
} catch (TransportException e) {
throw new RuntimeException(e);
}

return capabilities;
}

public FetchConnection getFetchConnection() throws TransportException {
try {
return getTransport().openFetch();
} catch (NotSupportedException e) {
return null;
}
}

public PushConnection getPushConnection() throws TransportException {
try {
return getTransport().openPush();
} catch (NotSupportedException e) {
return null;
}
}

public void setTransport(Transport transport) {
this.transport = transport;
}

public Transport getTransport() {
if (transport == null) {
throw new IllegalStateException("Transport was not initialized.");
}
return transport;
}

@Override
public void close() {
transport.close();
}
}

+ 67
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/internal/TransportFetchCommand.java View File

@@ -0,0 +1,67 @@
package org.eclipse.jgit.integrate.remotehelper.internal;

import org.eclipse.jgit.integrate.remotehelper.RemoteHelperCommand;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.FetchConnection;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class TransportFetchCommand extends RemoteHelperCommand {
private final RemoteHelperTransport provider;

public TransportFetchCommand(RemoteHelperTransport provider) {
super(provider.getContext());
this.provider = provider;
}

private ArrayList<FetchDefinition> defs = new ArrayList<>();

@Override
public void handle(List<String> arguments) throws Exception {
defs.add(new FetchDefinition(arguments.get(0), arguments.get(1)));
}

@Override
public void complete() throws Exception {
List<Ref> want = new ArrayList<>();
HashSet<ObjectId> have = new HashSet<>();

for (FetchDefinition def : defs) {
want.add(provider.getFetchConnection().getRef(def.getName()));
}

FetchConnection connection = provider.getFetchConnection();
connection.fetch(
new TextProgressMonitor(),
want,
have
);

connection.close();

defs.clear();
getContext().complete();
}

private static class FetchDefinition {
private final String sha;
private final String name;

FetchDefinition(String sha, String name) {
this.sha = sha;
this.name = name;
}

public String getSha() {
return sha;
}

public String getName() {
return name;
}
}
}

+ 39
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/internal/TransportListCommand.java View File

@@ -0,0 +1,39 @@
package org.eclipse.jgit.integrate.remotehelper.internal;

import org.eclipse.jgit.integrate.remotehelper.RemoteHelperCommand;
import org.eclipse.jgit.lib.Ref;

import java.util.List;
import java.util.Map;

public class TransportListCommand extends RemoteHelperCommand {
private final RemoteHelperTransport provider;

public TransportListCommand(RemoteHelperTransport provider) {
super(provider.getContext());
this.provider = provider;
}

@Override
public void handle(List<String> arguments) throws Exception {
Map<String, Ref> refs = provider.getFetchConnection().getRefsMap();

for (String key : refs.keySet()) {
Ref ref = refs.get(key);
StringBuilder builder = new StringBuilder();

if (ref.isSymbolic()) {
builder.append('@').append(ref.getTarget().getName());
} else if (ref.getObjectId() != null) {
builder.append(ref.getObjectId().name());
} else {
builder.append('?');
}

builder.append(' ').append(key);
getContext().reply(builder.toString());
}

getContext().complete();
}
}

+ 90
- 0
org.eclipse.jgit/src/org/eclipse/jgit/integrate/remotehelper/internal/TransportPushCommand.java View File

@@ -0,0 +1,90 @@
package org.eclipse.jgit.integrate.remotehelper.internal;

import org.eclipse.jgit.integrate.remotehelper.RemoteHelperCommand;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.PushConnection;
import org.eclipse.jgit.transport.RemoteRefUpdate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TransportPushCommand extends RemoteHelperCommand {
private final RemoteHelperTransport provider;

public TransportPushCommand(RemoteHelperTransport provider) {
super(provider.getContext());

this.provider = provider;
}

private List<PushDefinition> defs = new ArrayList<>();

@Override
public void handle(List<String> arguments) throws Exception {
String first = arguments.get(0);
if (first.startsWith("+")) {
first = first.substring(1);
}
String[] parts = first.split(":", 2);
defs.add(new PushDefinition(parts[0], parts[1]));
}

@Override
public void complete() throws Exception {
Map<String, RemoteRefUpdate> refUpdates = new HashMap<>();

for (PushDefinition def : defs) {
Ref local = getContext().getRepository().findRef(def.getSource());
RemoteRefUpdate refUpdate = new RemoteRefUpdate(
getContext().getRepository(),
local,
def.getDest(),
false,
def.getSource(),
null
);

refUpdates.put(def.getDest(), refUpdate);
}

PushConnection connection = provider.getPushConnection();

connection.push(
new TextProgressMonitor(),
refUpdates
);

for (String dest : refUpdates.keySet()) {
RemoteRefUpdate refUpdate = refUpdates.get(dest);
if (refUpdate.getStatus() == RemoteRefUpdate.Status.OK) {
getContext().reply("ok " + dest);
} else {
getContext().reply("error " + dest + " " + refUpdate.getStatus().name());
}
}

defs.clear();
getContext().complete();
}

private static class PushDefinition {
private final String source;
private final String dest;

PushDefinition(String src, String dst) {
this.source = src;
this.dest = dst;
}

public String getSource() {
return source;
}

public String getDest() {
return dest;
}
}
}

Loading…
Cancel
Save