|
|
@@ -4,36 +4,28 @@ import java.io.IOException;
|
|
|
import java.io.OutputStream;
|
|
|
import java.net.MalformedURLException;
|
|
|
import java.net.URL;
|
|
|
-import java.nio.ByteBuffer;
|
|
|
import java.nio.charset.Charset;
|
|
|
import java.util.HashMap;
|
|
|
-import java.util.Locale;
|
|
|
-import java.util.SortedSet;
|
|
|
import java.util.logging.Level;
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
import info.knacki.pass.git.entities.GitCommit;
|
|
|
import info.knacki.pass.git.entities.GitObject;
|
|
|
-import info.knacki.pass.git.entities.GitPackable;
|
|
|
-import info.knacki.pass.git.entities.GitPackableUtil;
|
|
|
import info.knacki.pass.git.entities.GitRef;
|
|
|
-import info.knacki.pass.io.CharsetHelper;
|
|
|
import info.knacki.pass.io.OnResponseListener;
|
|
|
import info.knacki.pass.io.OnStreamResponseListener;
|
|
|
-import info.knacki.pass.io.OutputStreamWithCheckSum;
|
|
|
import info.knacki.pass.settings.SettingsManager;
|
|
|
|
|
|
import static info.knacki.pass.io.NetworkUtils.ProtoPost;
|
|
|
import static info.knacki.pass.io.NetworkUtils.protoGet;
|
|
|
import static info.knacki.pass.io.NetworkUtils.protoInflateGet;
|
|
|
|
|
|
-class HttpGitProtocol implements GitInterface {
|
|
|
- private final SettingsManager.Git fConfig;
|
|
|
+class HttpGitProtocol extends BaseGitProtocol {
|
|
|
private GitRef[] fRefsCache = null;
|
|
|
private static final Logger log = Logger.getLogger(HttpGitProtocol.class.getName());
|
|
|
|
|
|
HttpGitProtocol(SettingsManager.Git config) {
|
|
|
- fConfig = config;
|
|
|
+ super(config);
|
|
|
}
|
|
|
|
|
|
public void GetRefs(final OnResponseListener<GitRef[]> callback) {
|
|
|
@@ -56,6 +48,11 @@ class HttpGitProtocol implements GitInterface {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+ if (fRefsCache[i] == null) {
|
|
|
+ fRefsCache = null;
|
|
|
+ callback.OnError("Cannot read references from repository", null);
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
callback.OnResponse(fRefsCache);
|
|
|
}
|
|
|
@@ -70,22 +67,8 @@ class HttpGitProtocol implements GitInterface {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void FetchCommit(final GitRef ref, final OnResponseListener<GitCommit> response) {
|
|
|
- PullHash(ref.GetHash(), new OnResponseListener<byte[]>() {
|
|
|
- @Override
|
|
|
- public void OnResponse(byte[] result) {
|
|
|
- response.OnResponse(new GitCommit(ref.GetHash(), new String(result, Charset.defaultCharset())));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void OnError(String msg, Throwable e) {
|
|
|
- response.OnError(msg, e);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
public void FetchTree(final GitCommit ci, final OnStreamResponseListener<GitObject.GitTree> response) {
|
|
|
- class RecursiveFetchTreeWalker implements OnResponseListener<byte[]> {
|
|
|
+ class RecursiveFetchTreeWalker implements OnStreamResponseListener<byte[]> {
|
|
|
private final GitObject.GitTree fRoot;
|
|
|
private GitObject.GitTree fCurrentTree;
|
|
|
private final OnStreamResponseListener<GitObject.GitTree> fResponseListener;
|
|
|
@@ -101,7 +84,7 @@ class HttpGitProtocol implements GitInterface {
|
|
|
|
|
|
@Override
|
|
|
public void OnResponse(byte[] result) {
|
|
|
- FillTree(fCurrentTree, result);
|
|
|
+ fCurrentTree.Fill(result);
|
|
|
fCurrentTree = fRoot.FindNextNotInitializedTree();
|
|
|
if (fCurrentTree != null)
|
|
|
PullHash(fCurrentTree.Initialize().GetHash());
|
|
|
@@ -114,6 +97,11 @@ class HttpGitProtocol implements GitInterface {
|
|
|
fResponseListener.OnError(msg, e);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public void OnMsg(String message) {
|
|
|
+ fResponseListener.OnMsg(message);
|
|
|
+ }
|
|
|
+
|
|
|
private void PullHash(String hash) {
|
|
|
fResponseListener.OnMsg("Reading tree " +hash);
|
|
|
HttpGitProtocol.this.PullHash(hash, this);
|
|
|
@@ -122,101 +110,16 @@ class HttpGitProtocol implements GitInterface {
|
|
|
private void PullHash(byte[] hash) {
|
|
|
PullHash(GitSha1.BytesToString(hash));
|
|
|
}
|
|
|
-
|
|
|
- private void FillTree(final GitObject.GitTree tree, byte[] data) {
|
|
|
- int i = 0;
|
|
|
-
|
|
|
- while (i < data.length) {
|
|
|
- byte[] mode = null;
|
|
|
- int len;
|
|
|
- for (len =0; i +len <data.length && len < 8; ++len) {
|
|
|
- if (data[i + len] == ' ') {
|
|
|
- mode = new byte[len];
|
|
|
- System.arraycopy(data, i, mode, 0, len);
|
|
|
- i += len + 1;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (mode == null)
|
|
|
- break;
|
|
|
- for (len =0; i +len < data.length && data[i +len] != 0; ++len);
|
|
|
- byte[] filenameBytes = new byte[len];
|
|
|
- System.arraycopy(data, i, filenameBytes, 0, len);
|
|
|
- i += len +1;
|
|
|
- if (i +20 > data.length)
|
|
|
- break;
|
|
|
- byte []sha1 = new byte[20];
|
|
|
- System.arraycopy(data, i, sha1, 0, 20);
|
|
|
- i += 20;
|
|
|
- tree.AddItem(GitObject.factory(tree, mode, CharsetHelper.ByteArrayToString(filenameBytes), sha1));
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
new RecursiveFetchTreeWalker(ci, response).run();
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public void FetchBlob(final GitObject.GitBlob blob, final OnResponseListener<byte[]> response) {
|
|
|
+ public void FetchBlob(final GitObject.GitBlob blob, final OnStreamResponseListener<byte[]> response) {
|
|
|
PullHash(GitSha1.BytesToString(blob.GetHash()), response);
|
|
|
}
|
|
|
|
|
|
- public void FetchHead(final OnStreamResponseListener<GitCommit> response) {
|
|
|
- GetRefs(new OnResponseListener<GitRef[]>() {
|
|
|
- @Override
|
|
|
- public void OnResponse(final GitRef[] result) {
|
|
|
- GitRef myRef = null;
|
|
|
- response.OnMsg("Found refs: ");
|
|
|
- for (GitRef ref: result) {
|
|
|
- response.OnMsg("\t> "+ref.GetBranch());
|
|
|
- if (ref.GetBranch().equals(fConfig.GetBranch()))
|
|
|
- myRef = ref;
|
|
|
- }
|
|
|
- if (myRef != null) {
|
|
|
- response.OnMsg("Checking out branch " +myRef.GetBranchName() +" revision " +myRef.GetHash());
|
|
|
- FetchCommit(myRef, new OnResponseListener<GitCommit>() {
|
|
|
- @Override
|
|
|
- public void OnResponse(final GitCommit result) {
|
|
|
- response.OnMsg("Finished read commit");
|
|
|
- response.OnMsg(result.GetMessage());
|
|
|
- response.OnMsg("Reading tree #" +GitSha1.BytesToString(result.GetTreeHash()));
|
|
|
- FetchTree(result, new OnStreamResponseListener<GitObject.GitTree>() {
|
|
|
- @Override
|
|
|
- public void OnMsg(String message) {
|
|
|
- response.OnMsg(message);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void OnResponse(GitObject.GitTree tree) {
|
|
|
- response.OnMsg("Finished reading tree");
|
|
|
- response.OnResponse(result);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void OnError(String msg, Throwable e) {
|
|
|
- response.OnError(msg, e);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void OnError(String msg, Throwable e) {
|
|
|
- response.OnError(msg, e);
|
|
|
- }
|
|
|
- });
|
|
|
- } else {
|
|
|
- response.OnError("Branch " +fConfig.GetBranch() + " not found on remote", null);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void OnError(final String msg, final Throwable e) {
|
|
|
- response.OnError(msg, e);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- private void PullHash(String hash, final OnResponseListener<byte[]> response) {
|
|
|
+ protected void PullHash(String hash, final OnStreamResponseListener<byte[]> response) {
|
|
|
URL url;
|
|
|
try {
|
|
|
url = new URL(fConfig.GetUrl() + "/objects/" + hash.substring(0, 2) + "/" + hash.substring(2));
|
|
|
@@ -228,81 +131,96 @@ class HttpGitProtocol implements GitInterface {
|
|
|
protoInflateGet(url, fConfig, response);
|
|
|
}
|
|
|
|
|
|
- public boolean makePack(SortedSet<GitPackable> objectsToPack, OutputStream out) throws IOException
|
|
|
- {
|
|
|
- OutputStreamWithCheckSum msg = new OutputStreamWithCheckSum(out);
|
|
|
- msg.write("PACK")
|
|
|
- .write(new byte[] { 0, 0, 0, 2 } )
|
|
|
- .write(ByteBuffer.allocate(4).putInt(objectsToPack.size()).array());
|
|
|
- for (GitPackable i: objectsToPack) {
|
|
|
- byte[] pack = i.GetPack();
|
|
|
- if (null == pack)
|
|
|
- return false;
|
|
|
- msg.write(GitPackableUtil.getObjHeader(i.GetPackableType(), pack.length))
|
|
|
- .write(GitPackableUtil.deflate(pack));
|
|
|
- log.info("Writing pack " +i.GetPackableType() +", " +GitSha1.getSha1OfPackable(i) +new String(i.GetPack()));
|
|
|
- }
|
|
|
- msg.writeSha1();
|
|
|
- return true;
|
|
|
+ public void FetchCommit(final GitRef ref, final OnStreamResponseListener<GitCommit> response) {
|
|
|
+ PullHash(ref.GetHash(), new OnStreamResponseListener<byte[]>() {
|
|
|
+ @Override
|
|
|
+ public void OnResponse(byte[] result) {
|
|
|
+ GitCommit ci = new GitCommit(ref.GetHash(), new String(result, Charset.defaultCharset()));
|
|
|
+ response.OnMsg("Finished read commit");
|
|
|
+ response.OnMsg(ci.GetMessage());
|
|
|
+ response.OnMsg("Reading tree #" +GitSha1.BytesToString(ci.GetTreeHash()));
|
|
|
+ FetchTree(ci, new OnStreamResponseListener<GitObject.GitTree>() {
|
|
|
+ @Override
|
|
|
+ public void OnMsg(String message) {
|
|
|
+ response.OnMsg(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void OnResponse(GitObject.GitTree tree) {
|
|
|
+ response.OnMsg("Finished reading tree");
|
|
|
+ response.OnResponse(ci);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void OnError(String msg, Throwable e) {
|
|
|
+ response.OnError(msg, e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void OnError(String msg, Throwable e) {
|
|
|
+ response.OnError(msg, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void OnMsg(String message) {
|
|
|
+ response.OnMsg(message);
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- public void PushBlobs(final GitCommit.Builder commit, final OnStreamResponseListener<Void> response) {
|
|
|
+ @Override
|
|
|
+ public void PushPack(final GitCommit commit, Pacman pack, final OnStreamResponseListener<Void> response) {
|
|
|
GetRefs(new OnResponseListener<GitRef[]>() {
|
|
|
@Override
|
|
|
public void OnResponse(final GitRef[] result) {
|
|
|
- GitRef myRef = null;
|
|
|
- for (GitRef ref: result) {
|
|
|
- if (ref.GetBranch().equals(fConfig.GetBranch()))
|
|
|
- myRef = ref;
|
|
|
+ final GitRef myRef = GetHeadRef(result);
|
|
|
+ if (myRef == null) {
|
|
|
+ response.OnError("Branch " +fConfig.GetBranch() + " not found on remote for pushing", null);
|
|
|
+ return;
|
|
|
}
|
|
|
- if (myRef != null) {
|
|
|
- final GitRef finalRef = myRef;
|
|
|
- response.OnMsg("Pushing over " +myRef.GetBranch() +" revision " +myRef.GetHash());
|
|
|
- try {
|
|
|
- HashMap<String, String> headers = new HashMap<>();
|
|
|
- headers.put("Content-Type", "application/x-git-receive-pack-request");
|
|
|
- ProtoPost(new URL(fConfig.GetUrl() +"/git-receive-pack"), headers, fConfig, new OnResponseListener<byte[]>() {
|
|
|
- @Override
|
|
|
- public void OnResponse(byte[] result) {
|
|
|
- response.OnResponse(null);
|
|
|
- }
|
|
|
+ response.OnMsg("Pushing over " +myRef.GetBranch() +" revision " +myRef.GetHash());
|
|
|
+ try {
|
|
|
+ HashMap<String, String> headers = new HashMap<>();
|
|
|
+ headers.put("Content-Type", "application/x-git-receive-pack-request");
|
|
|
+ ProtoPost(new URL(fConfig.GetUrl() +"/git-receive-pack"), headers, fConfig, new OnResponseListener<byte[]>() {
|
|
|
+ @Override
|
|
|
+ public void OnResponse(byte[] result) {
|
|
|
+ response.OnResponse(null);
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
- public void OnError(String msg, Throwable e) {
|
|
|
- log.log(Level.SEVERE, "git-receive-pack error", e);
|
|
|
- response.OnError(msg, e);
|
|
|
- }
|
|
|
- }, new OnResponseListener<OutputStream>() {
|
|
|
- @Override
|
|
|
- public void OnResponse(OutputStream result) {
|
|
|
- byte[] msgLine = (finalRef.GetHash() + " " + GitSha1.BytesToString(GitSha1.getRawSha1OfPackable(commit.Build())) +" " +finalRef.GetBranch()).getBytes();
|
|
|
- try {
|
|
|
- result.write(String.format(Locale.US, "%04X", msgLine.length +4).getBytes());
|
|
|
- result.write(msgLine);
|
|
|
- result.write("0000".getBytes());
|
|
|
- if (!makePack(commit.PreparePack(), result)) {
|
|
|
- OnError("Pack error", null);
|
|
|
- return;
|
|
|
- }
|
|
|
- result.close();
|
|
|
- }
|
|
|
- catch (IOException e) {
|
|
|
- log.log(Level.SEVERE, "Cannot git-upload-pack: " +e.getMessage(), e);
|
|
|
- OnError(e.getMessage(), e);
|
|
|
+ @Override
|
|
|
+ public void OnError(String msg, Throwable e) {
|
|
|
+ log.log(Level.SEVERE, "git-receive-pack error", e);
|
|
|
+ response.OnError(msg, e);
|
|
|
+ }
|
|
|
+ }, new OnResponseListener<OutputStream>() {
|
|
|
+ @Override
|
|
|
+ public void OnResponse(OutputStream result) {
|
|
|
+ try {
|
|
|
+ result.write(GitLine(myRef.GetHash() + " " + GitSha1.BytesToString(GitSha1.getRawSha1OfPackable(commit)) +" " +myRef.GetBranch()));
|
|
|
+ result.write(GitLine(null));
|
|
|
+ if (!pack.Write(result)) {
|
|
|
+ OnError("Pack error", null);
|
|
|
+ return;
|
|
|
}
|
|
|
+ result.close();
|
|
|
}
|
|
|
-
|
|
|
- @Override
|
|
|
- public void OnError(String msg, Throwable e) {
|
|
|
- response.OnError(msg, e);
|
|
|
+ catch (IOException e) {
|
|
|
+ log.log(Level.SEVERE, "Cannot git-upload-pack: " +e.getMessage(), e);
|
|
|
+ OnError(e.getMessage(), e);
|
|
|
}
|
|
|
- });
|
|
|
- }
|
|
|
- catch (IOException e) {
|
|
|
- response.OnError(e.getMessage(), e);
|
|
|
- }
|
|
|
- } else {
|
|
|
- response.OnError("Branch " +fConfig.GetBranch() + " not found on remote for pushing", null);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void OnError(String msg, Throwable e) {
|
|
|
+ response.OnError(msg, e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ catch (IOException e) {
|
|
|
+ response.OnError(e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
|