From 7b1204373dc44d16e4e443067825eb946905857a Mon Sep 17 00:00:00 2001 From: zeapo Date: Wed, 17 Dec 2014 23:33:30 +0100 Subject: add support for pull and push operations --- .../java/com/zeapo/pwdstore/git/GitActivity.java | 289 ++++++--------------- .../java/com/zeapo/pwdstore/git/GitOperation.java | 37 ++- .../java/com/zeapo/pwdstore/git/PullOperation.java | 36 +++ .../java/com/zeapo/pwdstore/git/PushOperation.java | 34 +++ 4 files changed, 174 insertions(+), 222 deletions(-) create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java (limited to 'app/src') diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java index dc7eb9d9..b841a42a 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -10,7 +10,6 @@ import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v7.app.ActionBarActivity; import android.text.Editable; -import android.text.InputType; import android.text.TextWatcher; import android.view.Menu; import android.view.MenuItem; @@ -18,41 +17,21 @@ import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.EditText; -import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.Session; -import com.jcraft.jsch.UserInfo; import com.zeapo.pwdstore.R; import com.zeapo.pwdstore.UserPreference; -import com.zeapo.pwdstore.git.config.GitConfigSessionFactory; -import com.zeapo.pwdstore.git.config.SshConfigSessionFactory; import com.zeapo.pwdstore.utils.PasswordRepository; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.apache.commons.io.FileUtils; -import org.eclipse.jgit.api.GitCommand; -import org.eclipse.jgit.api.PullCommand; -import org.eclipse.jgit.api.PushCommand; -import org.eclipse.jgit.errors.UnsupportedCredentialItem; -import org.eclipse.jgit.transport.CredentialItem; -import org.eclipse.jgit.transport.CredentialsProvider; -import org.eclipse.jgit.transport.CredentialsProviderUserInfo; -import org.eclipse.jgit.transport.JschConfigSessionFactory; -import org.eclipse.jgit.transport.OpenSshConfig; -import org.eclipse.jgit.transport.SshSessionFactory; -import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; -import org.eclipse.jgit.util.FS; import java.io.File; import java.io.IOException; -import java.lang.reflect.Method; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -131,9 +110,9 @@ public class GitActivity extends ActionBarActivity { new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapterView, View view, int i, long l) { - protocol = ((Spinner)findViewById(R.id.clone_protocol)).getSelectedItem().toString(); + protocol = ((Spinner) findViewById(R.id.clone_protocol)).getSelectedItem().toString(); if (protocol.equals("ssh://")) { - ((EditText)findViewById(R.id.clone_uri)).setHint("user@hostname:path"); + ((EditText) findViewById(R.id.clone_uri)).setHint("user@hostname:path"); ((EditText) findViewById(R.id.server_port)).setHint(R.string.default_ssh_port); @@ -141,7 +120,7 @@ public class GitActivity extends ActionBarActivity { connection_mode_spinner.setSelection(0); connection_mode_spinner.setEnabled(true); } else { - ((EditText)findViewById(R.id.clone_uri)).setHint("hostname/path"); + ((EditText) findViewById(R.id.clone_uri)).setHint("hostname/path"); ((EditText) findViewById(R.id.server_port)).setHint(R.string.default_https_port); @@ -164,7 +143,7 @@ public class GitActivity extends ActionBarActivity { final EditText server_port = ((EditText) findViewById(R.id.server_port)); final EditText server_path = ((EditText) findViewById(R.id.server_path)); final EditText server_user = ((EditText) findViewById(R.id.server_user)); - final EditText server_uri = ((EditText)findViewById(R.id.clone_uri)); + final EditText server_uri = ((EditText) findViewById(R.id.clone_uri)); View.OnFocusChangeListener updateListener = new View.OnFocusChangeListener() { @Override @@ -180,7 +159,8 @@ public class GitActivity extends ActionBarActivity { server_url.addTextChangedListener(new TextWatcher() { @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -189,11 +169,13 @@ public class GitActivity extends ActionBarActivity { } @Override - public void afterTextChanged(Editable editable) { } + public void afterTextChanged(Editable editable) { + } }); server_port.addTextChangedListener(new TextWatcher() { @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -202,11 +184,13 @@ public class GitActivity extends ActionBarActivity { } @Override - public void afterTextChanged(Editable editable) { } + public void afterTextChanged(Editable editable) { + } }); server_user.addTextChangedListener(new TextWatcher() { @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -215,11 +199,13 @@ public class GitActivity extends ActionBarActivity { } @Override - public void afterTextChanged(Editable editable) { } + public void afterTextChanged(Editable editable) { + } }); server_path.addTextChangedListener(new TextWatcher() { @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -228,7 +214,8 @@ public class GitActivity extends ActionBarActivity { } @Override - public void afterTextChanged(Editable editable) { } + public void afterTextChanged(Editable editable) { + } }); server_uri.addTextChangedListener(new TextWatcher() { @@ -247,8 +234,7 @@ public class GitActivity extends ActionBarActivity { } }); - if (operationCode == EDIT_SERVER) - { + if (operationCode == EDIT_SERVER) { findViewById(R.id.clone_button).setVisibility(View.INVISIBLE); findViewById(R.id.save_button).setVisibility(View.VISIBLE); } else { @@ -259,18 +245,20 @@ public class GitActivity extends ActionBarActivity { break; case REQUEST_PULL: - authenticateAndRun("pullOperation"); + pullFromRepository(); break; case REQUEST_PUSH: - authenticateAndRun("pushOperation"); + pushToRepository(); break; } } - /** Fills in the server_uri field with the information coming from other fields */ + /** + * Fills in the server_uri field with the information coming from other fields + */ private void updateURI() { EditText uri = (EditText) findViewById(R.id.clone_uri); EditText server_url = ((EditText) findViewById(R.id.server_url)); @@ -278,11 +266,9 @@ public class GitActivity extends ActionBarActivity { EditText server_path = ((EditText) findViewById(R.id.server_path)); EditText server_user = ((EditText) findViewById(R.id.server_user)); - if (uri != null) { - switch (protocol) - { - case "ssh://": - { + if (uri != null) { + switch (protocol) { + case "ssh://": { String hostname = server_user.getText() + "@" + @@ -306,8 +292,7 @@ public class GitActivity extends ActionBarActivity { if (!hostname.equals("@:")) uri.setText(hostname); } break; - case "https://": - { + case "https://": { StringBuilder hostname = new StringBuilder(); hostname.append(server_url.getText().toString().trim()); @@ -325,13 +310,15 @@ public class GitActivity extends ActionBarActivity { } break; default: - break; + break; } } } - /** Splits the information in server_uri into the other fields */ + /** + * Splits the information in server_uri into the other fields + */ private void splitURI() { EditText server_uri = (EditText) findViewById(R.id.clone_uri); EditText server_url = ((EditText) findViewById(R.id.server_url)); @@ -399,6 +386,7 @@ public class GitActivity extends ActionBarActivity { /** * Clones the repository, the directory exists, deletes it + * * @param view */ public void cloneRepository(View view) { @@ -448,7 +436,15 @@ public class GitActivity extends ActionBarActivity { public void onClick(DialogInterface dialog, int id) { try { FileUtils.deleteDirectory(localDir); - authenticateAndRun("cloneOperation"); + try { + new CloneOperation(localDir, activity) + .setCommand(hostname) + .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + } catch (Exception e) { + //This is what happens when jgit fails :( + //TODO Handle the diffent cases of exceptions + e.printStackTrace(); + } } catch (IOException e) { //TODO Handle the exception correctly if we are unable to delete the directory... e.printStackTrace(); @@ -471,7 +467,6 @@ public class GitActivity extends ActionBarActivity { show(); } else { try { -// authenticateAndRun("cloneOperation"); new CloneOperation(localDir, activity) .setCommand(hostname) .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); @@ -486,6 +481,7 @@ public class GitActivity extends ActionBarActivity { /** * Save the repository information to the shared preferences settings + * * @param view */ public void saveConfiguration(View view) { @@ -525,11 +521,10 @@ public class GitActivity extends ActionBarActivity { new GitAsyncTask(activity, true, false, CloneCommand.class).execute(cmd); } - public void pullOperation(UsernamePasswordCredentialsProvider provider) { - + public void pullFromRepository() { if (settings.getString("git_remote_username", "").isEmpty() || - settings.getString("git_remote_server", "").isEmpty() || - settings.getString("git_remote_location", "").isEmpty() ) + settings.getString("git_remote_server", "").isEmpty() || + settings.getString("git_remote_location", "").isEmpty()) new AlertDialog.Builder(this) .setMessage(activity.getResources().getString(R.string.set_information_dialog_text)) .setPositiveButton(activity.getResources().getString(R.string.dialog_positive), new DialogInterface.OnClickListener() { @@ -551,34 +546,22 @@ public class GitActivity extends ActionBarActivity { else { // check that the remote origin is here, else add it - PasswordRepository.addRemote("origin", settings.getString("git_remote_username", "user") - + "@" + - settings.getString("git_remote_server", "server.com").trim() - + ":" + - settings.getString("git_remote_location", "path/to/repository"), false); - - GitCommand cmd; - if (provider != null) - cmd = new Git(PasswordRepository.getRepository(new File(""))) - .pull() - .setRebase(true) - .setRemote("origin") - .setCredentialsProvider(provider); - else - cmd = new Git(PasswordRepository.getRepository(new File(""))) - .pull() - .setRebase(true) - .setRemote("origin"); - - new GitAsyncTask(activity, true, false, PullCommand.class).execute(cmd); + PasswordRepository.addRemote("origin", hostname, false); + + try { + new PullOperation(localDir, activity) + .setCommand(hostname) + .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + } catch (Exception e) { + e.printStackTrace(); + } } } - - public void pushOperation(UsernamePasswordCredentialsProvider provider) { + public void pushToRepository() { if (settings.getString("git_remote_username", "user").isEmpty() || settings.getString("git_remote_server", "server.com").trim().isEmpty() || - settings.getString("git_remote_location", "path/to/repository").isEmpty() ) + settings.getString("git_remote_location", "path/to/repository").isEmpty()) new AlertDialog.Builder(this) .setMessage("You have to set the information about the server before synchronizing with the server") .setPositiveButton("On my way!", new DialogInterface.OnClickListener() { @@ -600,138 +583,15 @@ public class GitActivity extends ActionBarActivity { else { // check that the remote origin is here, else add it - PasswordRepository.addRemote("origin", settings.getString("git_remote_username", "user") - + "@" + - settings.getString("git_remote_server", "server.com").trim() - + ":" + - settings.getString("git_remote_location", "path/to/repository"), false); - - GitCommand cmd; - if (provider != null) - cmd = new Git(PasswordRepository.getRepository(new File(""))) - .push() - .setPushAll() - .setRemote("origin") - .setCredentialsProvider(provider); - else - cmd = new Git(PasswordRepository.getRepository(new File(""))) - .push() - .setPushAll() - .setRemote("origin"); - - - new GitAsyncTask(activity, true, false, PushCommand.class).execute(cmd); - } - } - - /** Finds the method and provides it with authentication paramters via invokeWithAuthentication */ - private void authenticateAndRun(String operation) { - try { - invokeWithAuthentication(this, GitActivity.class.getMethod(operation, UsernamePasswordCredentialsProvider.class)); - } catch (Exception e) { - e.printStackTrace(); - } - } + PasswordRepository.addRemote("origin", hostname, false); - /** Calls a method encapsulating a GitCommand and providing it with authentication parameters - * - * @param activity - * @param method - */ - private void invokeWithAuthentication(final GitActivity activity, final Method method) { - - if (connectionMode.equalsIgnoreCase("ssh-key")) { - final File sshKey = new File(getFilesDir() + "/.ssh_key"); - if (!sshKey.exists()) { - new AlertDialog.Builder(this) - .setMessage(activity.getResources().getString(R.string.ssh_preferences_dialog_text)) - .setTitle(activity.getResources().getString(R.string.ssh_preferences_dialog_title)) - .setPositiveButton(activity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - try { - Intent intent = new Intent(getApplicationContext(), UserPreference.class); - intent.putExtra("operation", "get_ssh_key"); - startActivityForResult(intent, GitOperation.GET_SSH_KEY_FROM_CLONE); - } catch (Exception e) { - System.out.println("Exception caught :("); - e.printStackTrace(); - } - } - }).setNegativeButton(activity.getResources().getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // Do nothing... - } - }).show(); - } else { - final EditText passphrase = new EditText(activity); - passphrase.setHint("Passphrase"); - passphrase.setWidth(LinearLayout.LayoutParams.MATCH_PARENT); - passphrase.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); - - new AlertDialog.Builder(activity) - .setTitle(activity.getResources().getString(R.string.passphrase_dialog_title)) - .setMessage(activity.getResources().getString(R.string.passphrase_dialog_text)) - .setView(passphrase) - .setPositiveButton(activity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - - SshSessionFactory.setInstance(new GitConfigSessionFactory()); - try { - - JschConfigSessionFactory sessionFactory = new SshConfigSessionFactory(sshKey.getAbsolutePath(), - settings.getString("git_remote_username", "git"), - passphrase.getText().toString()); - SshSessionFactory.setInstance(sessionFactory); - - try { - method.invoke(activity, (UsernamePasswordCredentialsProvider) null); - } catch (Exception e){ - e.printStackTrace(); - } - - } catch (Exception e){ - e.printStackTrace(); - } - - } - }).setNegativeButton(activity.getResources().getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - // Do nothing. - } - }).show(); + try { + new PushOperation(localDir, activity) + .setCommand(hostname) + .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + } catch (Exception e) { + e.printStackTrace(); } - } else { - final EditText password = new EditText(activity); - password.setHint("Password"); - password.setWidth(LinearLayout.LayoutParams.MATCH_PARENT); - password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); - - new AlertDialog.Builder(activity) - .setTitle(activity.getResources().getString(R.string.passphrase_dialog_title)) - .setMessage(activity.getResources().getString(R.string.password_dialog_text)) - .setView(password) - .setPositiveButton(activity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - - SshSessionFactory.setInstance(new GitConfigSessionFactory()); - try { - method.invoke(activity, - new UsernamePasswordCredentialsProvider( - settings.getString("git_remote_username", "git"), - password.getText().toString()) - ); - } catch (Exception e){ - e.printStackTrace(); - } - - } - }).setNegativeButton(activity.getResources().getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - // Do nothing. - } - }).show(); } } @@ -747,11 +607,22 @@ public class GitActivity extends ActionBarActivity { switch (requestCode) { case REQUEST_PULL: - authenticateAndRun("pullOperation"); + try { + new PullOperation(localDir, activity) + .setCommand(hostname) + .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + } catch (Exception e) { + e.printStackTrace(); + } break; case REQUEST_PUSH: - authenticateAndRun("pushOperation"); - break; + try { + new PushOperation(localDir, activity) + .setCommand(hostname) + .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + } catch (Exception e) { + e.printStackTrace(); + } break; case GitOperation.GET_SSH_KEY_FROM_CLONE: try { new CloneOperation(localDir, activity) diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java index e8659229..65436969 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java @@ -36,7 +36,8 @@ public abstract class GitOperation { /** * Creates a new git operation - * @param fileDir the git working tree directory + * + * @param fileDir the git working tree directory * @param callingActivity the calling activity */ public GitOperation(File fileDir, Activity callingActivity) { @@ -46,20 +47,22 @@ public abstract class GitOperation { /** * Sets the authentication using user/pwd scheme + * * @param username the username * @param password the password * @return the current object */ public GitOperation setAuthentication(String username, String password) { SshSessionFactory.setInstance(new GitConfigSessionFactory()); - this.provider = new UsernamePasswordCredentialsProvider(username,password); + this.provider = new UsernamePasswordCredentialsProvider(username, password); return this; } /** * Sets the authentication using ssh-key scheme - * @param sshKey the ssh-key file - * @param username the username + * + * @param sshKey the ssh-key file + * @param username the username * @param passphrase the passphrase * @return the current object */ @@ -72,13 +75,21 @@ public abstract class GitOperation { /** * Executes the GitCommand in an async task + * * @throws Exception */ public void execute() throws Exception { - Log.d(TAG, command + " << "); - new GitAsyncTask(callingActivity, true, false, CloneCommand.class).execute(command); + new GitAsyncTask(callingActivity, true, false, GitCommand.class).execute(command); } + /** + * Executes the GitCommand in an async task after creating the authentication + * + * @param connectionMode the server-connection mode + * @param username the username + * @param sshKey the ssh-key file + * @throws Exception + */ public void executeAfterAuthentication(String connectionMode, final String username, @Nullable final File sshKey) throws Exception { if (connectionMode.equalsIgnoreCase("ssh-key")) { if (sshKey == null || !sshKey.exists()) { @@ -89,6 +100,8 @@ public abstract class GitOperation { @Override public void onClick(DialogInterface dialog, int id) { try { + // Ask the UserPreference to provide us with the ssh-key + // onResult has to be handled by the callingActivity Intent intent = new Intent(callingActivity.getApplicationContext(), UserPreference.class); intent.putExtra("operation", "get_ssh_key"); callingActivity.startActivityForResult(intent, GET_SSH_KEY_FROM_CLONE); @@ -115,11 +128,10 @@ public abstract class GitOperation { .setView(passphrase) .setPositiveButton(callingActivity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - - SshSessionFactory.setInstance(new GitConfigSessionFactory()); try { + // Authenticate using the ssh-key and then execute the command setAuthentication(sshKey, username, passphrase.getText().toString()).execute(); - } catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); } @@ -142,11 +154,10 @@ public abstract class GitOperation { .setView(password) .setPositiveButton(callingActivity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - - setAuthentication(username, password.getText().toString()); + // authenticate using the user/pwd and then execute the command try { - execute(); - } catch (Exception e){ + setAuthentication(username, password.getText().toString()).execute(); + } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java new file mode 100644 index 00000000..0d43216d --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java @@ -0,0 +1,36 @@ +package com.zeapo.pwdstore.git; + +import android.app.Activity; + +import com.zeapo.pwdstore.utils.PasswordRepository; + +import org.eclipse.jgit.api.Git; + +import java.io.File; + +public class PullOperation extends GitOperation { + + /** + * Creates a new git operation + * + * @param fileDir the git working tree directory + * @param callingActivity the calling activity + */ + public PullOperation(File fileDir, Activity callingActivity) { + super(fileDir, callingActivity); + } + + /** + * Sets the command using the repository uri + * @param uri the uri of the repository + * @return the current object + */ + public PullOperation setCommand(String uri) { + this.command = new Git(repository) + .pull() + .setRebase(true) + .setRemote("origin") + .setCredentialsProvider(provider); + return this; + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java new file mode 100644 index 00000000..fa3e4dd9 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java @@ -0,0 +1,34 @@ +package com.zeapo.pwdstore.git; + +import android.app.Activity; + +import org.eclipse.jgit.api.Git; + +import java.io.File; + +public class PushOperation extends GitOperation { + + /** + * Creates a new git operation + * + * @param fileDir the git working tree directory + * @param callingActivity the calling activity + */ + public PushOperation(File fileDir, Activity callingActivity) { + super(fileDir, callingActivity); + } + + /** + * Sets the command using the repository uri + * @param uri the uri of the repository + * @return the current object + */ + public PushOperation setCommand(String uri) { + this.command = new Git(repository) + .push() + .setPushAll() + .setRemote("origin") + .setCredentialsProvider(provider); + return this; + } +} -- cgit v1.2.3