|
|
@@ -2,9 +2,9 @@ package info.knacki.pass.git;
|
|
|
|
|
|
import android.os.AsyncTask;
|
|
|
|
|
|
-import java.io.BufferedReader;
|
|
|
+import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
-import java.io.InputStreamReader;
|
|
|
+import java.io.InputStream;
|
|
|
import java.math.BigInteger;
|
|
|
import java.net.Authenticator;
|
|
|
import java.net.MalformedURLException;
|
|
|
@@ -13,6 +13,7 @@ import java.net.URL;
|
|
|
import java.net.URLConnection;
|
|
|
import java.nio.charset.Charset;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Map;
|
|
|
import java.util.logging.Level;
|
|
|
import java.util.logging.Logger;
|
|
|
import java.util.zip.InflaterInputStream;
|
|
|
@@ -22,115 +23,140 @@ import info.knacki.pass.git.entities.GitObject;
|
|
|
import info.knacki.pass.git.entities.GitRef;
|
|
|
import info.knacki.pass.settings.SettingsManager;
|
|
|
|
|
|
-class DumbGitInterface implements GitInterface {
|
|
|
- protected final SettingsManager.Git fConfig;
|
|
|
- protected GitRef[] fRefsCache = null;
|
|
|
- private static final Logger log = Logger.getLogger(DumbGitInterface.class.getName());
|
|
|
+class HttpGitProtocol implements GitInterface {
|
|
|
+ private final SettingsManager.Git fConfig;
|
|
|
+ private GitRef[] fRefsCache = null;
|
|
|
+ private static final Logger log = Logger.getLogger(HttpGitProtocol.class.getName());
|
|
|
|
|
|
- DumbGitInterface(SettingsManager.Git config) {
|
|
|
+ HttpGitProtocol(SettingsManager.Git config) {
|
|
|
fConfig = config;
|
|
|
}
|
|
|
|
|
|
- void protoInflateGet(final URL url, final OnResponseListener<byte[]> callback) {
|
|
|
- AsyncTask<Void, Void, Integer> task = new AsyncTask<Void, Void, Integer>() {
|
|
|
- @Override
|
|
|
- protected Integer doInBackground(Void... voids) {
|
|
|
- try {
|
|
|
- log.log(Level.INFO, "fetching " +url.toString());
|
|
|
- URLConnection httpClient = url.openConnection();
|
|
|
- if (fConfig.HasAuthentification()) {
|
|
|
- Authenticator.setDefault(new Authenticator() {
|
|
|
- @Override
|
|
|
- protected PasswordAuthentication getPasswordAuthentication() {
|
|
|
- return new PasswordAuthentication(fConfig.GetUser(), fConfig.GetPassword().toCharArray());
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- InflaterInputStream in = new InflaterInputStream(httpClient.getInputStream());
|
|
|
- ArrayList<byte[]> fullBuffer = new ArrayList<>();
|
|
|
- int totalRead = 0;
|
|
|
- byte[] buffer = new byte[1024];
|
|
|
- int currentRead;
|
|
|
- while ((currentRead = in.read(buffer, 0, 1024)) != 0) {
|
|
|
- fullBuffer.add(buffer);
|
|
|
- buffer = new byte[1024];
|
|
|
- totalRead += currentRead;
|
|
|
- if (currentRead < 1024)
|
|
|
- break;
|
|
|
- }
|
|
|
- in.close();
|
|
|
- buffer = new byte[totalRead];
|
|
|
- int i =0;
|
|
|
- for (byte []currentBuf: fullBuffer) {
|
|
|
- for (int j =0; j < currentBuf.length && i*1024+j < totalRead; ++j) {
|
|
|
- buffer[i*1024 +j] = currentBuf[j];
|
|
|
- }
|
|
|
- ++i;
|
|
|
- }
|
|
|
+ static class DownloaderTask extends AsyncTask<Void, Void, Integer> {
|
|
|
+ private final URL fUrl;
|
|
|
+ private OnResponseListener<byte[]> fResp;
|
|
|
+ private final SettingsManager.Git fConfig;
|
|
|
|
|
|
- for (i =0; i < totalRead && buffer[i] != 0; ++i);
|
|
|
- if (i != totalRead) {
|
|
|
- ++i;
|
|
|
- byte []arr = new byte[buffer.length -i];
|
|
|
- System.arraycopy(buffer, i, arr, 0, totalRead -i);
|
|
|
- callback.onResponse(arr);
|
|
|
- } else {
|
|
|
- callback.onResponse(buffer);
|
|
|
- }
|
|
|
+ DownloaderTask(URL url, SettingsManager.Git config, OnResponseListener<byte[]> resp) {
|
|
|
+ fUrl = url;
|
|
|
+ fResp = resp;
|
|
|
+ fConfig = config;
|
|
|
+ }
|
|
|
+
|
|
|
+ DownloaderTask(URL url, SettingsManager.Git config) {
|
|
|
+ fUrl = url;
|
|
|
+ fConfig = config;
|
|
|
+ }
|
|
|
+
|
|
|
+ void SetResultHandler(OnResponseListener<byte[]> handler) {
|
|
|
+ fResp = handler;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected InputStream GetInputFilter(URLConnection in) throws IOException {
|
|
|
+ return in.getInputStream();
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void ManageResponse(byte[] resp) {
|
|
|
+ fResp.onResponse(resp);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected Integer doInBackground(Void... voids) {
|
|
|
+ try {
|
|
|
+ log.log(Level.INFO, "fetching " +fUrl.toString());
|
|
|
+ URLConnection httpClient = fUrl.openConnection();
|
|
|
+ if (fConfig.HasAuthentification()) {
|
|
|
+ Authenticator.setDefault(new Authenticator() {
|
|
|
+ @Override
|
|
|
+ protected PasswordAuthentication getPasswordAuthentication() {
|
|
|
+ return new PasswordAuthentication(fConfig.GetUser(), fConfig.GetPassword().toCharArray());
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
- catch (MalformedURLException e) {
|
|
|
- log.log(Level.WARNING, e.getMessage(), e);
|
|
|
- callback.onError(e.getClass().getSimpleName() +": " +e.getMessage(), e);
|
|
|
+ InputStream in = GetInputFilter(httpClient);
|
|
|
+ ArrayList<byte[]> fullBuffer = new ArrayList<>();
|
|
|
+ int totalRead = 0;
|
|
|
+ byte[] buffer = new byte[1024];
|
|
|
+ int currentRead;
|
|
|
+ while ((currentRead = in.read(buffer, 0, 1024)) != 0) {
|
|
|
+ fullBuffer.add(buffer);
|
|
|
+ buffer = new byte[1024];
|
|
|
+ totalRead += currentRead;
|
|
|
+ if (currentRead < 1024)
|
|
|
+ break;
|
|
|
}
|
|
|
- catch (IOException e) {
|
|
|
- log.log(Level.WARNING, e.getMessage(), e);
|
|
|
- callback.onError(e.getClass().getSimpleName() +": " +e.getMessage(), e);
|
|
|
+ in.close();
|
|
|
+ buffer = new byte[totalRead];
|
|
|
+ int i =0;
|
|
|
+ for (byte []currentBuf: fullBuffer) {
|
|
|
+ for (int j =0; j < currentBuf.length && i*1024+j < totalRead; ++j) {
|
|
|
+ buffer[i*1024 +j] = currentBuf[j];
|
|
|
+ }
|
|
|
+ ++i;
|
|
|
}
|
|
|
- return 0;
|
|
|
+ ManageResponse(buffer);
|
|
|
+ }
|
|
|
+ catch (IOException e) {
|
|
|
+ log.log(Level.WARNING, e.getMessage(), e);
|
|
|
+ fResp.onError(e.getClass().getSimpleName() +": " +e.getMessage(), e);
|
|
|
}
|
|
|
- };
|
|
|
- task.execute();
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- void protoGet(final URL url, final OnResponseListener<String> callback) {
|
|
|
- AsyncTask<Void, Void, Integer> task = new AsyncTask<Void, Void, Integer>() {
|
|
|
- @Override
|
|
|
- protected Integer doInBackground(Void... voids) {
|
|
|
- try {
|
|
|
- log.log(Level.INFO, "fetching " +url.toString());
|
|
|
- URLConnection httpClient = url.openConnection();
|
|
|
- if (fConfig.HasAuthentification()) {
|
|
|
- Authenticator.setDefault(new Authenticator() {
|
|
|
- @Override
|
|
|
- protected PasswordAuthentication getPasswordAuthentication() {
|
|
|
- return new PasswordAuthentication(fConfig.GetUser(), fConfig.GetPassword().toCharArray());
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- BufferedReader in = new BufferedReader(new InputStreamReader(httpClient.getInputStream()));
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- String buf;
|
|
|
- while((buf = in.readLine()) != null)
|
|
|
- {
|
|
|
- if (sb.length() != 0)
|
|
|
- sb.append("\n");
|
|
|
- sb.append(buf);
|
|
|
- }
|
|
|
- in.close();
|
|
|
- callback.onResponse(sb.toString());
|
|
|
- }
|
|
|
- catch (MalformedURLException e) {
|
|
|
- log.log(Level.WARNING, e.getMessage(), e);
|
|
|
- callback.onError(e.getClass().getSimpleName() +": " +e.getMessage(), e);
|
|
|
+ static class DownloaderWithInflaterTask extends DownloaderTask {
|
|
|
+ DownloaderWithInflaterTask(URL url, SettingsManager.Git config, OnResponseListener<byte[]> resp) {
|
|
|
+ super(url, config, resp);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected InputStream GetInputFilter(URLConnection in) throws IOException {
|
|
|
+ return new InflaterInputStream(super.GetInputFilter(in));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void ManageResponse(byte[] result) {
|
|
|
+ int i =0;
|
|
|
+
|
|
|
+ while (i < result.length && result[i] != 0)
|
|
|
+ ++i;
|
|
|
+ if (i != result.length) {
|
|
|
+ ++i;
|
|
|
+ byte []arr = new byte[result.length -i];
|
|
|
+ System.arraycopy(result, i, arr, 0, result.length -i);
|
|
|
+ super.ManageResponse(arr);
|
|
|
+ } else {
|
|
|
+ super.ManageResponse(result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ static class StringDownloaderTask extends DownloaderTask {
|
|
|
+ private final OnResponseListener<String> onResp;
|
|
|
+
|
|
|
+ StringDownloaderTask(URL url, SettingsManager.Git config, OnResponseListener<String> resultHandler) {
|
|
|
+ super(url, config);
|
|
|
+ SetResultHandler(new OnResponseListener<byte[]>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(byte[] result) {
|
|
|
+ StringDownloaderTask.this.onResp.onResponse(new String(result, Charset.defaultCharset()));
|
|
|
}
|
|
|
- catch (IOException e) {
|
|
|
- log.log(Level.WARNING, e.getMessage(), e);
|
|
|
- callback.onError(e.getClass().getSimpleName() +": " +e.getMessage(), e);
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(String msg, Throwable e) {
|
|
|
+ StringDownloaderTask.this.onResp.onError(msg, e);
|
|
|
}
|
|
|
- return 0;
|
|
|
- }
|
|
|
- };
|
|
|
- task.execute();
|
|
|
+ });
|
|
|
+ onResp = resultHandler;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void protoInflateGet(final URL url, final OnResponseListener<byte[]> callback) {
|
|
|
+ new DownloaderWithInflaterTask(url, fConfig, callback).execute();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void protoGet(final URL url, final OnResponseListener<String> callback) {
|
|
|
+ new StringDownloaderTask(url, fConfig, callback).execute();
|
|
|
}
|
|
|
|
|
|
public void GetRefs(final OnResponseListener<GitRef[]> callback) {
|
|
|
@@ -213,19 +239,25 @@ class DumbGitInterface implements GitInterface {
|
|
|
|
|
|
private void PullHash(String hash) {
|
|
|
fResponseListener.onMsg("Reading tree " +hash);
|
|
|
- DumbGitInterface.this.PullHash(hash, this);
|
|
|
+ HttpGitProtocol.this.PullHash(hash, this);
|
|
|
}
|
|
|
|
|
|
private void FillTree(final GitObject.GitTree tree, byte[] data) {
|
|
|
int i = 0;
|
|
|
|
|
|
while (i < data.length) {
|
|
|
- byte[] mode = new byte[6];
|
|
|
- if (i +6 >= 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;
|
|
|
- System.arraycopy(data, i, mode, 0, 6);
|
|
|
- i += 6;
|
|
|
- int len = 0;
|
|
|
+ len = 0;
|
|
|
while (i +len < data.length && data[i +len] != 0)
|
|
|
++len;
|
|
|
byte[] filenameBytes = new byte[len];
|
|
|
@@ -237,7 +269,7 @@ class DumbGitInterface implements GitInterface {
|
|
|
byte []sha1 = new byte[21];
|
|
|
System.arraycopy(data, i, sha1, 0, 21);
|
|
|
i += 21;
|
|
|
- tree.AddItem(GitObject.factory(tree, new String(mode, Charset.defaultCharset()).toCharArray(), fileName, sha1ToString(sha1)));
|
|
|
+ tree.AddItem(GitObject.factory(tree, mode, fileName, sha1ToString(sha1)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -326,4 +358,33 @@ class DumbGitInterface implements GitInterface {
|
|
|
}
|
|
|
protoInflateGet(url, response);
|
|
|
}
|
|
|
+
|
|
|
+ public void debugTree(String rootGit, GitObject.GitTree tree) {
|
|
|
+ log.severe(">>> DEBUG >> Tree hash is " +GitSha1.getSha1OfObject(rootGit, tree));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void PushBlobs(String rootGit, GitObject.GitTree tree, final Map<String, GitObject.GitBlob> blobs, final File[] files, final GitInterface.OnStreamResponseListener<Void> response) {
|
|
|
+ GetRefs(new GitInterface.OnResponseListener<GitRef[]>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(final GitRef[] result) {
|
|
|
+ GitRef myref = null;
|
|
|
+ for (GitRef ref: result) {
|
|
|
+ if (ref.GetBranch().equals(fConfig.GetBranch()))
|
|
|
+ myref = ref;
|
|
|
+ }
|
|
|
+ if (myref != null) {
|
|
|
+ response.onMsg("Pushing over " +myref.GetBranchName() +" revision " +myref.GetHash());
|
|
|
+ // FIXME
|
|
|
+ response.onResponse(null);
|
|
|
+ } else {
|
|
|
+ response.onError("Branch " +fConfig.GetBranch() + " not found on remote for pushing", null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(final String msg, final Throwable e) {
|
|
|
+ response.onError(msg, e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|