From f48bd5faa01c191f355fd5ebdc2e98f0579b591f Mon Sep 17 00:00:00 2001 From: zeapo Date: Wed, 17 Dec 2014 22:55:45 +0100 Subject: git tasks refactoring (clone working) --- app/src/main/AndroidManifest.xml | 2 +- .../java/com/zeapo/pwdstore/PasswordStore.java | 28 +- .../java/com/zeapo/pwdstore/UserPreference.java | 6 +- .../com/zeapo/pwdstore/git/CloneOperation.java | 54 ++ .../java/com/zeapo/pwdstore/git/GitActivity.java | 768 +++++++++++++++++++ .../java/com/zeapo/pwdstore/git/GitHandler.java | 825 --------------------- .../java/com/zeapo/pwdstore/git/GitOperation.java | 161 ++++ .../git/config/GitConfigSessionFactory.java | 24 + .../git/config/SshConfigSessionFactory.java | 70 ++ app/src/main/res/layout/activity_git_clone.xml | 2 +- app/src/main/res/menu/git_clone.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 12 files changed, 1098 insertions(+), 846 deletions(-) create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java delete mode 100644 app/src/main/java/com/zeapo/pwdstore/git/GitHandler.java create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.java create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/config/SshConfigSessionFactory.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4a124c94..cc21dc54 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ - diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java index f7107eff..2af74075 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java @@ -18,8 +18,8 @@ import android.view.MenuItem; import android.view.View; import com.zeapo.pwdstore.crypto.PgpHandler; +import com.zeapo.pwdstore.git.GitActivity; import com.zeapo.pwdstore.git.GitAsyncTask; -import com.zeapo.pwdstore.git.GitHandler; import com.zeapo.pwdstore.utils.PasswordItem; import com.zeapo.pwdstore.utils.PasswordRecyclerAdapter; import com.zeapo.pwdstore.utils.PasswordRepository; @@ -151,9 +151,9 @@ public class PasswordStore extends ActionBarActivity { break; } - intent = new Intent(this, GitHandler.class); - intent.putExtra("Operation", GitHandler.REQUEST_PUSH); - startActivityForResult(intent, GitHandler.REQUEST_PUSH); + intent = new Intent(this, GitActivity.class); + intent.putExtra("Operation", GitActivity.REQUEST_PUSH); + startActivityForResult(intent, GitActivity.REQUEST_PUSH); this.leftActivity = true; return true; @@ -163,9 +163,9 @@ public class PasswordStore extends ActionBarActivity { break; } - intent = new Intent(this, GitHandler.class); - intent.putExtra("Operation", GitHandler.REQUEST_PULL); - startActivityForResult(intent, GitHandler.REQUEST_PULL); + intent = new Intent(this, GitActivity.class); + intent.putExtra("Operation", GitActivity.REQUEST_PULL); + startActivityForResult(intent, GitActivity.REQUEST_PULL); this.leftActivity = true; return true; @@ -186,9 +186,9 @@ public class PasswordStore extends ActionBarActivity { } public void getClone(View view){ - Intent intent = new Intent(this, GitHandler.class); - intent.putExtra("Operation", GitHandler.REQUEST_CLONE); - startActivityForResult(intent, GitHandler.REQUEST_CLONE); + Intent intent = new Intent(this, GitActivity.class); + intent.putExtra("Operation", GitActivity.REQUEST_CLONE); + startActivityForResult(intent, GitActivity.REQUEST_CLONE); } private void createRepository() { @@ -228,7 +228,7 @@ public class PasswordStore extends ActionBarActivity { @Override public void onClick(DialogInterface dialogInterface, int i) { Intent intent = new Intent(activity, UserPreference.class); - startActivityForResult(intent, GitHandler.REQUEST_INIT); + startActivityForResult(intent, GitActivity.REQUEST_INIT); } }) .setNegativeButton(this.getResources().getString(R.string.dialog_negative), new DialogInterface.OnClickListener() { @@ -433,7 +433,7 @@ public class PasswordStore extends ActionBarActivity { protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { - if (requestCode == GitHandler.REQUEST_CLONE) + if (requestCode == GitActivity.REQUEST_CLONE) checkLocalRepository(); switch (requestCode) { @@ -446,10 +446,10 @@ public class PasswordStore extends ActionBarActivity { ); refreshListAdapter(); break; - case GitHandler.REQUEST_INIT: + case GitActivity.REQUEST_INIT: initRepository(getCurrentFocus()); break; - case GitHandler.REQUEST_PULL: + case GitActivity.REQUEST_PULL: updateListAdapter(); break; } diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index 89c1cd36..65c7e484 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -12,7 +12,7 @@ import android.util.Log; import android.view.MenuItem; import com.zeapo.pwdstore.crypto.PgpHandler; -import com.zeapo.pwdstore.git.GitHandler; +import com.zeapo.pwdstore.git.GitActivity; import com.zeapo.pwdstore.utils.PasswordRepository; import org.apache.commons.io.FileUtils; @@ -105,8 +105,8 @@ public class UserPreference extends ActionBarActivity implements Preference.OnPr break; case "git_server_info": { - Intent intent = new Intent(this, GitHandler.class); - intent.putExtra("Operation", GitHandler.EDIT_SERVER); + Intent intent = new Intent(this, GitActivity.class); + intent.putExtra("Operation", GitActivity.EDIT_SERVER); startActivityForResult(intent, EDIT_GIT_INFO); } break; diff --git a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java new file mode 100644 index 00000000..0445b114 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java @@ -0,0 +1,54 @@ +package com.zeapo.pwdstore.git; + +import android.app.Activity; + +import org.eclipse.jgit.api.CloneCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; + +import java.io.File; + +public class CloneOperation extends GitOperation { + private static final String TAG = "CLONEOPT"; + + /** + * Creates a new clone operation + * @param fileDir the git working tree directory + * @param callingActivity the calling activity + */ + public CloneOperation(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 CloneOperation setCommand(String uri) { + this.command = Git.cloneRepository(). + setCredentialsProvider(provider). + setCloneAllBranches(true). + setDirectory(repository.getWorkTree()). + setURI(uri); + return this; + } + + /** + * sets the authentication for user/pwd scheme + * @param username the username + * @param password the password + * @return the current object + */ + @Override + public CloneOperation setAuthentication(String username, String password) { + super.setAuthentication(username, password); + return this; + } + + @Override + public CloneOperation setAuthentication(File sshKey, String username, String passphrase) { + super.setAuthentication(sshKey, username, passphrase); + return this; + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java new file mode 100644 index 00000000..dc7eb9d9 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -0,0 +1,768 @@ +package com.zeapo.pwdstore.git; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +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; +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; + +// TODO move the messages to strings.xml + +public class GitActivity extends ActionBarActivity { + + private Activity activity; + private Context context; + + private String protocol; + private String connectionMode; + + private File localDir; + private String hostname; + private String username; + private String port; + + private SharedPreferences settings; + + public static final int REQUEST_PULL = 101; + public static final int REQUEST_PUSH = 102; + public static final int REQUEST_CLONE = 103; + public static final int REQUEST_INIT = 104; + public static final int EDIT_SERVER = 105; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + context = getApplicationContext(); + activity = this; + + settings = PreferenceManager.getDefaultSharedPreferences(this.context); + + protocol = settings.getString("git_remote_protocol", "ssh://"); + connectionMode = settings.getString("git_remote_auth", "ssh-key"); + int operationCode = getIntent().getExtras().getInt("Operation"); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + switch (operationCode) { + case REQUEST_CLONE: + case EDIT_SERVER: + setContentView(R.layout.activity_git_clone); + + final Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol); + final Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode); + + + // init the spinner for connection modes + final ArrayAdapter connection_mode_adapter = ArrayAdapter.createFromResource(this, + R.array.connection_modes, android.R.layout.simple_spinner_item); + connection_mode_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + connection_mode_spinner.setAdapter(connection_mode_adapter); + connection_mode_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + String selection = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString(); + connectionMode = selection; + settings.edit().putString("git_remote_auth", selection).apply(); + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + + } + }); + + // init the spinner for protocols + ArrayAdapter protocol_adapter = ArrayAdapter.createFromResource(this, + R.array.clone_protocols, android.R.layout.simple_spinner_item); + protocol_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + protcol_spinner.setAdapter(protocol_adapter); + protcol_spinner.setOnItemSelectedListener( + new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + 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.server_port)).setHint(R.string.default_ssh_port); + + // select ssh-key auth mode as default and enable the spinner in case it was disabled + connection_mode_spinner.setSelection(0); + connection_mode_spinner.setEnabled(true); + } else { + ((EditText)findViewById(R.id.clone_uri)).setHint("hostname/path"); + + ((EditText) findViewById(R.id.server_port)).setHint(R.string.default_https_port); + + // select user/pwd auth-mode and disable the spinner + connection_mode_spinner.setSelection(1); + connection_mode_spinner.setEnabled(false); + } + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + + } + } + ); + + + // init the server information + final EditText server_url = ((EditText) findViewById(R.id.server_url)); + 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)); + + View.OnFocusChangeListener updateListener = new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View view, boolean b) { + updateURI(); + } + }; + + server_url.setText(settings.getString("git_remote_server", "")); + server_port.setText(settings.getString("git_remote_port", "")); + server_user.setText(settings.getString("git_remote_username", "")); + server_path.setText(settings.getString("git_remote_location", "")); + + server_url.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + if (server_url.isFocused()) + updateURI(); + } + + @Override + public void afterTextChanged(Editable editable) { } + }); + server_port.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + if (server_port.isFocused()) + updateURI(); + } + + @Override + public void afterTextChanged(Editable editable) { } + }); + server_user.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + if (server_user.isFocused()) + updateURI(); + } + + @Override + public void afterTextChanged(Editable editable) { } + }); + server_path.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + if (server_path.isFocused()) + updateURI(); + } + + @Override + public void afterTextChanged(Editable editable) { } + }); + + server_uri.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + if (server_uri.isFocused()) + splitURI(); + } + + @Override + public void afterTextChanged(Editable editable) { + } + }); + + if (operationCode == EDIT_SERVER) + { + findViewById(R.id.clone_button).setVisibility(View.INVISIBLE); + findViewById(R.id.save_button).setVisibility(View.VISIBLE); + } else { + findViewById(R.id.clone_button).setVisibility(View.VISIBLE); + findViewById(R.id.save_button).setVisibility(View.INVISIBLE); + } + + + break; + case REQUEST_PULL: + authenticateAndRun("pullOperation"); + break; + + case REQUEST_PUSH: + authenticateAndRun("pushOperation"); + break; + } + + + } + + /** 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)); + EditText server_port = ((EditText) findViewById(R.id.server_port)); + 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://": + { + String hostname = + server_user.getText() + + "@" + + server_url.getText().toString().trim() + + ":"; + if (server_port.getText().toString().equals("22")) { + hostname += server_path.getText().toString(); + + ((TextView) findViewById(R.id.warn_url)).setVisibility(View.GONE); + } else { + TextView warn_url = (TextView) findViewById(R.id.warn_url); + if (!server_path.getText().toString().matches("/.*") && !server_port.getText().toString().isEmpty()) { + warn_url.setText(R.string.warn_malformed_url_port); + warn_url.setVisibility(View.VISIBLE); + } else { + warn_url.setVisibility(View.GONE); + } + hostname += server_port.getText().toString() + server_path.getText().toString(); + } + + if (!hostname.equals("@:")) uri.setText(hostname); + } + break; + case "https://": + { + StringBuilder hostname = new StringBuilder(); + hostname.append(server_url.getText().toString().trim()); + + if (server_port.getText().toString().equals("443")) { + hostname.append(server_path.getText().toString()); + + ((TextView) findViewById(R.id.warn_url)).setVisibility(View.GONE); + } else { + hostname.append("/"); + hostname.append(server_port.getText().toString()) + .append(server_path.getText().toString()); + } + + if (!hostname.toString().equals("@/")) uri.setText(hostname); + } + break; + default: + break; + } + + } + } + + /** 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)); + EditText server_port = ((EditText) findViewById(R.id.server_port)); + EditText server_path = ((EditText) findViewById(R.id.server_path)); + EditText server_user = ((EditText) findViewById(R.id.server_user)); + + String uri = server_uri.getText().toString(); + Pattern pattern = Pattern.compile("(.+)@([\\w\\d\\.]+):([\\d]+)*(.*)"); + Matcher matcher = pattern.matcher(uri); + if (matcher.find()) { + int count = matcher.groupCount(); + if (count > 1) { + server_user.setText(matcher.group(1)); + server_url.setText(matcher.group(2)); + } + if (count == 4) { + server_port.setText(matcher.group(3)); + server_path.setText(matcher.group(4)); + + TextView warn_url = (TextView) findViewById(R.id.warn_url); + if (!server_path.getText().toString().matches("/.*") && !server_port.getText().toString().isEmpty()) { + warn_url.setText(R.string.warn_malformed_url_port); + warn_url.setVisibility(View.VISIBLE); + } else { + warn_url.setVisibility(View.GONE); + } + } + } + } + + @Override + public void onResume() { + super.onResume(); + updateURI(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.git_clone, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + switch (id) { + case R.id.user_pref: + try { + Intent intent = new Intent(this, UserPreference.class); + startActivity(intent); + } catch (Exception e) { + System.out.println("Exception caught :("); + e.printStackTrace(); + } + return true; + + } + return super.onOptionsItemSelected(item); + } + + /** + * Clones the repository, the directory exists, deletes it + * @param view + */ + public void cloneRepository(View view) { + localDir = new File(getApplicationContext().getFilesDir().getAbsoluteFile() + "/store"); + + hostname = ((EditText) findViewById(R.id.clone_uri)).getText().toString(); + port = ((EditText) findViewById(R.id.server_port)).getText().toString(); + // don't ask the user, take off the protocol that he puts in + hostname = hostname.replaceFirst("^.+://", ""); + ((TextView) findViewById(R.id.clone_uri)).setText(hostname); + + // now cheat a little and prepend the real protocol + // jGit does not accept a ssh:// but requires https:// + if (!protocol.equals("ssh://")) { + hostname = protocol + hostname; + } else { + + // if the port is explicitly given, jgit requires the ssh:// + if (!port.isEmpty()) + hostname = protocol + hostname; + + // did he forget the username? + if (!hostname.matches("^.+@.+")) { + new AlertDialog.Builder(this). + setMessage(activity.getResources().getString(R.string.forget_username_dialog_text)). + setPositiveButton(activity.getResources().getString(R.string.dialog_oops), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + + } + }). + show(); + return; + } + + username = hostname.split("@")[0]; + } + + + if (localDir.exists()) { + new AlertDialog.Builder(this). + setTitle(R.string.dialog_delete_title). + setMessage(R.string.dialog_delete_msg). + setCancelable(false). + setPositiveButton(R.string.dialog_delete, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + try { + FileUtils.deleteDirectory(localDir); + authenticateAndRun("cloneOperation"); + } catch (IOException e) { + //TODO Handle the exception correctly if we are unable to delete the directory... + e.printStackTrace(); + } catch (Exception e) { + //This is what happens when jgit fails :( + //TODO Handle the diffent cases of exceptions + } + + dialog.cancel(); + } + } + ). + setNegativeButton(R.string.dialog_do_not_delete, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + } + ). + show(); + } else { + try { +// authenticateAndRun("cloneOperation"); + 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(); + } + } + } + + + /** + * Save the repository information to the shared preferences settings + * @param view + */ + public void saveConfiguration(View view) { + // remember the settings + SharedPreferences.Editor editor = settings.edit(); + + editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); + editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); + editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); + editor.putString("git_remote_protocol", protocol); + editor.putString("git_remote_auth", connectionMode); + editor.putString("git_remote_port", port); + editor.commit(); + + PasswordRepository.addRemote("origin", ((EditText) findViewById(R.id.clone_uri)).getText().toString(), true); + } + + public void cloneOperation(UsernamePasswordCredentialsProvider provider) { + + // remember the settings + SharedPreferences.Editor editor = settings.edit(); + + editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); + editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); + editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); + editor.putString("git_remote_protocol", protocol); + editor.putString("git_remote_auth", connectionMode); + editor.putString("git_remote_port", port); + editor.commit(); + + CloneCommand cmd = Git.cloneRepository(). + setCredentialsProvider(provider). + setCloneAllBranches(true). + setDirectory(localDir). + setURI(hostname); + + new GitAsyncTask(activity, true, false, CloneCommand.class).execute(cmd); + } + + public void pullOperation(UsernamePasswordCredentialsProvider provider) { + + if (settings.getString("git_remote_username", "").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() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(activity, UserPreference.class); + startActivityForResult(intent, REQUEST_PULL); + } + }) + .setNegativeButton(activity.getResources().getString(R.string.dialog_negative), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + // do nothing :( + setResult(RESULT_OK); + finish(); + } + }) + .show(); + + 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); + } + } + + + public void pushOperation(UsernamePasswordCredentialsProvider provider) { + 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() ) + 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() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(activity, UserPreference.class); + startActivityForResult(intent, REQUEST_PUSH); + } + }) + .setNegativeButton("Nah... later", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + // do nothing :( + setResult(RESULT_OK); + finish(); + } + }) + .show(); + + 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(); + } + } + + /** 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(); + } + } 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(); + } + } + + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + if (resultCode == RESULT_CANCELED) { + setResult(RESULT_CANCELED); + finish(); + return; + } + + if (resultCode == RESULT_OK) { + + switch (requestCode) { + case REQUEST_PULL: + authenticateAndRun("pullOperation"); + break; + case REQUEST_PUSH: + authenticateAndRun("pushOperation"); + break; + case GitOperation.GET_SSH_KEY_FROM_CLONE: + try { + new CloneOperation(localDir, activity) + .setCommand(hostname) + .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + } catch (Exception e) { + e.printStackTrace(); + } + } + + } + } + +} diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitHandler.java b/app/src/main/java/com/zeapo/pwdstore/git/GitHandler.java deleted file mode 100644 index 85872d65..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitHandler.java +++ /dev/null @@ -1,825 +0,0 @@ -package com.zeapo.pwdstore.git; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -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; -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.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; - -// TODO move the messages to strings.xml - -public class GitHandler extends ActionBarActivity { - - private Activity activity; - private Context context; - - private String protocol; - private String connectionMode; - - private File localDir; - private String hostname; - private String username; - private String port; - - private SharedPreferences settings; - - public static final int REQUEST_PULL = 101; - public static final int REQUEST_PUSH = 102; - public static final int REQUEST_CLONE = 103; - public static final int REQUEST_INIT = 104; - public static final int EDIT_SERVER = 105; - - private static final int GET_SSH_KEY_FROM_CLONE = 201; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - context = getApplicationContext(); - activity = this; - - settings = PreferenceManager.getDefaultSharedPreferences(this.context); - - protocol = settings.getString("git_remote_protocol", "ssh://"); - connectionMode = settings.getString("git_remote_auth", "ssh-key"); - int operationCode = getIntent().getExtras().getInt("Operation"); - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - switch (operationCode) { - case REQUEST_CLONE: - case EDIT_SERVER: - setContentView(R.layout.activity_git_clone); - - final Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol); - final Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode); - - - // init the spinner for connection modes - final ArrayAdapter connection_mode_adapter = ArrayAdapter.createFromResource(this, - R.array.connection_modes, android.R.layout.simple_spinner_item); - connection_mode_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - connection_mode_spinner.setAdapter(connection_mode_adapter); - connection_mode_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView adapterView, View view, int i, long l) { - String selection = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString(); - connectionMode = selection; - settings.edit().putString("git_remote_auth", selection).apply(); - } - - @Override - public void onNothingSelected(AdapterView adapterView) { - - } - }); - - // init the spinner for protocols - ArrayAdapter protocol_adapter = ArrayAdapter.createFromResource(this, - R.array.clone_protocols, android.R.layout.simple_spinner_item); - protocol_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - protcol_spinner.setAdapter(protocol_adapter); - protcol_spinner.setOnItemSelectedListener( - new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView adapterView, View view, int i, long l) { - 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.server_port)).setHint(R.string.default_ssh_port); - - // select ssh-key auth mode as default and enable the spinner in case it was disabled - connection_mode_spinner.setSelection(0); - connection_mode_spinner.setEnabled(true); - } else { - ((EditText)findViewById(R.id.clone_uri)).setHint("hostname/path"); - - ((EditText) findViewById(R.id.server_port)).setHint(R.string.default_https_port); - - // select user/pwd auth-mode and disable the spinner - connection_mode_spinner.setSelection(1); - connection_mode_spinner.setEnabled(false); - } - } - - @Override - public void onNothingSelected(AdapterView adapterView) { - - } - } - ); - - - // init the server information - final EditText server_url = ((EditText) findViewById(R.id.server_url)); - 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)); - - View.OnFocusChangeListener updateListener = new View.OnFocusChangeListener() { - @Override - public void onFocusChange(View view, boolean b) { - updateURI(); - } - }; - - server_url.setText(settings.getString("git_remote_server", "")); - server_port.setText(settings.getString("git_remote_port", "")); - server_user.setText(settings.getString("git_remote_username", "")); - server_path.setText(settings.getString("git_remote_location", "")); - - server_url.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - if (server_url.isFocused()) - updateURI(); - } - - @Override - public void afterTextChanged(Editable editable) { } - }); - server_port.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - if (server_port.isFocused()) - updateURI(); - } - - @Override - public void afterTextChanged(Editable editable) { } - }); - server_user.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - if (server_user.isFocused()) - updateURI(); - } - - @Override - public void afterTextChanged(Editable editable) { } - }); - server_path.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - if (server_path.isFocused()) - updateURI(); - } - - @Override - public void afterTextChanged(Editable editable) { } - }); - - server_uri.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - if (server_uri.isFocused()) - splitURI(); - } - - @Override - public void afterTextChanged(Editable editable) { - } - }); - - if (operationCode == EDIT_SERVER) - { - findViewById(R.id.clone_button).setVisibility(View.INVISIBLE); - findViewById(R.id.save_button).setVisibility(View.VISIBLE); - } else { - findViewById(R.id.clone_button).setVisibility(View.VISIBLE); - findViewById(R.id.save_button).setVisibility(View.INVISIBLE); - } - - - break; - case REQUEST_PULL: - authenticateAndRun("pullOperation"); - break; - - case REQUEST_PUSH: - authenticateAndRun("pushOperation"); - break; - } - - - } - - /** 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)); - EditText server_port = ((EditText) findViewById(R.id.server_port)); - 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://": - { - String hostname = - server_user.getText() - + "@" + - server_url.getText().toString().trim() - + ":"; - if (server_port.getText().toString().equals("22")) { - hostname += server_path.getText().toString(); - - ((TextView) findViewById(R.id.warn_url)).setVisibility(View.GONE); - } else { - TextView warn_url = (TextView) findViewById(R.id.warn_url); - if (!server_path.getText().toString().matches("/.*") && !server_port.getText().toString().isEmpty()) { - warn_url.setText(R.string.warn_malformed_url_port); - warn_url.setVisibility(View.VISIBLE); - } else { - warn_url.setVisibility(View.GONE); - } - hostname += server_port.getText().toString() + server_path.getText().toString(); - } - - if (!hostname.equals("@:")) uri.setText(hostname); - } - break; - case "https://": - { - StringBuilder hostname = new StringBuilder(); - hostname.append(server_url.getText().toString().trim()); - - if (server_port.getText().toString().equals("443")) { - hostname.append(server_path.getText().toString()); - - ((TextView) findViewById(R.id.warn_url)).setVisibility(View.GONE); - } else { - hostname.append("/"); - hostname.append(server_port.getText().toString()) - .append(server_path.getText().toString()); - } - - if (!hostname.toString().equals("@/")) uri.setText(hostname); - } - break; - default: - break; - } - - } - } - - /** 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)); - EditText server_port = ((EditText) findViewById(R.id.server_port)); - EditText server_path = ((EditText) findViewById(R.id.server_path)); - EditText server_user = ((EditText) findViewById(R.id.server_user)); - - String uri = server_uri.getText().toString(); - Pattern pattern = Pattern.compile("(.+)@([\\w\\d\\.]+):([\\d]+)*(.*)"); - Matcher matcher = pattern.matcher(uri); - if (matcher.find()) { - int count = matcher.groupCount(); - if (count > 1) { - server_user.setText(matcher.group(1)); - server_url.setText(matcher.group(2)); - } - if (count == 4) { - server_port.setText(matcher.group(3)); - server_path.setText(matcher.group(4)); - - TextView warn_url = (TextView) findViewById(R.id.warn_url); - if (!server_path.getText().toString().matches("/.*") && !server_port.getText().toString().isEmpty()) { - warn_url.setText(R.string.warn_malformed_url_port); - warn_url.setVisibility(View.VISIBLE); - } else { - warn_url.setVisibility(View.GONE); - } - } - } - } - - @Override - public void onResume() { - super.onResume(); - updateURI(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.git_clone, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. - int id = item.getItemId(); - switch (id) { - case R.id.user_pref: - try { - Intent intent = new Intent(this, UserPreference.class); - startActivity(intent); - } catch (Exception e) { - System.out.println("Exception caught :("); - e.printStackTrace(); - } - return true; - - } - return super.onOptionsItemSelected(item); - } - - protected class GitConfigSessionFactory extends JschConfigSessionFactory { - - protected void configure(OpenSshConfig.Host hc, Session session) { - session.setConfig("StrictHostKeyChecking", "no"); - } - - @Override - protected JSch - getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException { - JSch jsch = super.getJSch(hc, fs); - jsch.removeAllIdentity(); - return jsch; - } - } - - protected class SshConfigSessionFactory extends GitConfigSessionFactory { - private String sshKey; - private String passphrase; - - public SshConfigSessionFactory(String sshKey, String passphrase) { - this.sshKey = sshKey; - this.passphrase = passphrase; - } - - @Override - protected JSch - getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException { - JSch jsch = super.getJSch(hc, fs); - jsch.removeAllIdentity(); - jsch.addIdentity(sshKey); - return jsch; - } - - @Override - protected void configure(OpenSshConfig.Host hc, Session session) { - session.setConfig("StrictHostKeyChecking", "no"); - - CredentialsProvider provider = new CredentialsProvider() { - @Override - public boolean isInteractive() { - return false; - } - - @Override - public boolean supports(CredentialItem... items) { - return true; - } - - @Override - public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem { - for (CredentialItem item : items) { - if (item instanceof CredentialItem.Username) { - ((CredentialItem.Username) item).setValue(settings.getString("git_remote_username", "git")); - continue; - } - if (item instanceof CredentialItem.StringType) { - ((CredentialItem.StringType) item).setValue(passphrase); - } - } - return true; - } - }; - UserInfo userInfo = new CredentialsProviderUserInfo(session, provider); - session.setUserInfo(userInfo); - } - } - - - /** - * Clones the repository, the directory exists, deletes it - * @param view - */ - public void cloneRepository(View view) { - localDir = new File(getApplicationContext().getFilesDir().getAbsoluteFile() + "/store"); - - hostname = ((EditText) findViewById(R.id.clone_uri)).getText().toString(); - port = ((EditText) findViewById(R.id.server_port)).getText().toString(); - // don't ask the user, take off the protocol that he puts in - hostname = hostname.replaceFirst("^.+://", ""); - ((TextView) findViewById(R.id.clone_uri)).setText(hostname); - - // now cheat a little and prepend the real protocol - // jGit does not accept a ssh:// but requires https:// - if (!protocol.equals("ssh://")) { - hostname = protocol + hostname; - } else { - - // if the port is explicitly given, jgit requires the ssh:// - if (!port.isEmpty()) - hostname = protocol + hostname; - - // did he forget the username? - if (!hostname.matches("^.+@.+")) { - new AlertDialog.Builder(this). - setMessage(activity.getResources().getString(R.string.forget_username_dialog_text)). - setPositiveButton(activity.getResources().getString(R.string.dialog_oops), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }). - show(); - return; - } - - username = hostname.split("@")[0]; - } - - - if (localDir.exists()) { - new AlertDialog.Builder(this). - setTitle(R.string.dialog_delete_title). - setMessage(R.string.dialog_delete_msg). - setCancelable(false). - setPositiveButton(R.string.dialog_delete, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - try { - FileUtils.deleteDirectory(localDir); - authenticateAndRun("cloneOperation"); - } catch (IOException e) { - //TODO Handle the exception correctly if we are unable to delete the directory... - e.printStackTrace(); - } catch (Exception e) { - //This is what happens when jgit fails :( - //TODO Handle the diffent cases of exceptions - } - - dialog.cancel(); - } - } - ). - setNegativeButton(R.string.dialog_do_not_delete, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - } - ). - show(); - } else { - try { - authenticateAndRun("cloneOperation"); - } catch (Exception e) { - //This is what happens when jgit fails :( - //TODO Handle the diffent cases of exceptions - e.printStackTrace(); - } - } - } - - - /** - * Save the repository information to the shared preferences settings - * @param view - */ - public void saveConfiguration(View view) { - // remember the settings - SharedPreferences.Editor editor = settings.edit(); - - editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); - editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); - editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); - editor.putString("git_remote_protocol", protocol); - editor.putString("git_remote_auth", connectionMode); - editor.putString("git_remote_port", port); - editor.commit(); - - PasswordRepository.addRemote("origin", ((EditText) findViewById(R.id.clone_uri)).getText().toString(), true); - } - - public void cloneOperation(UsernamePasswordCredentialsProvider provider) { - - // remember the settings - SharedPreferences.Editor editor = settings.edit(); - - editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); - editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); - editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); - editor.putString("git_remote_protocol", protocol); - editor.putString("git_remote_auth", connectionMode); - editor.putString("git_remote_port", port); - editor.commit(); - - CloneCommand cmd = Git.cloneRepository(). - setCredentialsProvider(provider). - setCloneAllBranches(true). - setDirectory(localDir). - setURI(hostname); - - new GitAsyncTask(activity, true, false, CloneCommand.class).execute(cmd); - } - - public void pullOperation(UsernamePasswordCredentialsProvider provider) { - - if (settings.getString("git_remote_username", "").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() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - Intent intent = new Intent(activity, UserPreference.class); - startActivityForResult(intent, REQUEST_PULL); - } - }) - .setNegativeButton(activity.getResources().getString(R.string.dialog_negative), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - // do nothing :( - setResult(RESULT_OK); - finish(); - } - }) - .show(); - - 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); - } - } - - - public void pushOperation(UsernamePasswordCredentialsProvider provider) { - 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() ) - 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() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - Intent intent = new Intent(activity, UserPreference.class); - startActivityForResult(intent, REQUEST_PUSH); - } - }) - .setNegativeButton("Nah... later", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - // do nothing :( - setResult(RESULT_OK); - finish(); - } - }) - .show(); - - 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, GitHandler.class.getMethod(operation, UsernamePasswordCredentialsProvider.class)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** Calls a method encapsulating a GitCommand and providing it with authentication parameters - * - * @param activity - * @param method - */ - private void invokeWithAuthentication(final GitHandler 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, 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(), 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(); - } - } 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(); - } - } - - protected void onActivityResult(int requestCode, int resultCode, - Intent data) { - if (resultCode == RESULT_CANCELED) { - setResult(RESULT_CANCELED); - finish(); - return; - } - - if (resultCode == RESULT_OK) { - - switch (requestCode) { - case REQUEST_PULL: - authenticateAndRun("pullOperation"); - break; - case REQUEST_PUSH: - authenticateAndRun("pushOperation"); - break; - case GET_SSH_KEY_FROM_CLONE: - authenticateAndRun("cloneOperation"); - } - - } - } - -} diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java new file mode 100644 index 00000000..e8659229 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java @@ -0,0 +1,161 @@ +package com.zeapo.pwdstore.git; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.support.annotation.Nullable; +import android.text.InputType; +import android.util.Log; +import android.widget.EditText; +import android.widget.LinearLayout; + +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.GitCommand; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.JschConfigSessionFactory; +import org.eclipse.jgit.transport.SshSessionFactory; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; + +import java.io.File; + +public abstract class GitOperation { + private static final String TAG = "GitOpt"; + public static final int GET_SSH_KEY_FROM_CLONE = 201; + + protected final Repository repository; + protected final Activity callingActivity; + protected UsernamePasswordCredentialsProvider provider; + protected GitCommand command; + + /** + * Creates a new git operation + * @param fileDir the git working tree directory + * @param callingActivity the calling activity + */ + public GitOperation(File fileDir, Activity callingActivity) { + this.repository = PasswordRepository.getRepository(fileDir); + this.callingActivity = callingActivity; + } + + /** + * 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); + return this; + } + + /** + * Sets the authentication using ssh-key scheme + * @param sshKey the ssh-key file + * @param username the username + * @param passphrase the passphrase + * @return the current object + */ + public GitOperation setAuthentication(File sshKey, String username, String passphrase) { + JschConfigSessionFactory sessionFactory = new SshConfigSessionFactory(sshKey.getAbsolutePath(), username, passphrase); + SshSessionFactory.setInstance(sessionFactory); + this.provider = null; + return this; + } + + /** + * 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); + } + + public void executeAfterAuthentication(String connectionMode, final String username, @Nullable final File sshKey) throws Exception { + if (connectionMode.equalsIgnoreCase("ssh-key")) { + if (sshKey == null || !sshKey.exists()) { + new AlertDialog.Builder(callingActivity) + .setMessage(callingActivity.getResources().getString(R.string.ssh_preferences_dialog_text)) + .setTitle(callingActivity.getResources().getString(R.string.ssh_preferences_dialog_title)) + .setPositiveButton(callingActivity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + try { + Intent intent = new Intent(callingActivity.getApplicationContext(), UserPreference.class); + intent.putExtra("operation", "get_ssh_key"); + callingActivity.startActivityForResult(intent, GET_SSH_KEY_FROM_CLONE); + } catch (Exception e) { + System.out.println("Exception caught :("); + e.printStackTrace(); + } + } + }).setNegativeButton(callingActivity.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(callingActivity); + passphrase.setHint("Passphrase"); + passphrase.setWidth(LinearLayout.LayoutParams.MATCH_PARENT); + passphrase.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + + new AlertDialog.Builder(callingActivity) + .setTitle(callingActivity.getResources().getString(R.string.passphrase_dialog_title)) + .setMessage(callingActivity.getResources().getString(R.string.passphrase_dialog_text)) + .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 { + setAuthentication(sshKey, username, passphrase.getText().toString()).execute(); + } catch (Exception e){ + e.printStackTrace(); + } + + } + }).setNegativeButton(callingActivity.getResources().getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + // Do nothing. + } + }).show(); + } + } else { + final EditText password = new EditText(callingActivity); + password.setHint("Password"); + password.setWidth(LinearLayout.LayoutParams.MATCH_PARENT); + password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + + new AlertDialog.Builder(callingActivity) + .setTitle(callingActivity.getResources().getString(R.string.passphrase_dialog_title)) + .setMessage(callingActivity.getResources().getString(R.string.password_dialog_text)) + .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()); + try { + execute(); + } catch (Exception e){ + e.printStackTrace(); + } + + } + }).setNegativeButton(callingActivity.getResources().getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + // Do nothing. + } + }).show(); + } + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.java b/app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.java new file mode 100644 index 00000000..ab23361e --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.java @@ -0,0 +1,24 @@ +package com.zeapo.pwdstore.git.config; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; + +import org.eclipse.jgit.transport.JschConfigSessionFactory; +import org.eclipse.jgit.transport.OpenSshConfig; +import org.eclipse.jgit.util.FS; + +public class GitConfigSessionFactory extends JschConfigSessionFactory { + + protected void configure(OpenSshConfig.Host hc, Session session) { + session.setConfig("StrictHostKeyChecking", "no"); + } + + @Override + protected JSch + getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException { + JSch jsch = super.getJSch(hc, fs); + jsch.removeAllIdentity(); + return jsch; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zeapo/pwdstore/git/config/SshConfigSessionFactory.java b/app/src/main/java/com/zeapo/pwdstore/git/config/SshConfigSessionFactory.java new file mode 100644 index 00000000..333a6325 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/config/SshConfigSessionFactory.java @@ -0,0 +1,70 @@ +package com.zeapo.pwdstore.git.config; + +import android.content.SharedPreferences; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import com.jcraft.jsch.UserInfo; + +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.OpenSshConfig; +import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.util.FS; + +public class SshConfigSessionFactory extends GitConfigSessionFactory { + private String sshKey; + private String passphrase; + private String username; + + public SshConfigSessionFactory(String sshKey, String username, String passphrase) { + this.sshKey = sshKey; + this.passphrase = passphrase; + this.username = username; + } + + @Override + protected JSch + getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException { + JSch jsch = super.getJSch(hc, fs); + jsch.removeAllIdentity(); + jsch.addIdentity(sshKey); + return jsch; + } + + @Override + protected void configure(OpenSshConfig.Host hc, Session session) { + session.setConfig("StrictHostKeyChecking", "no"); + + CredentialsProvider provider = new CredentialsProvider() { + @Override + public boolean isInteractive() { + return false; + } + + @Override + public boolean supports(CredentialItem... items) { + return true; + } + + @Override + public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem { + for (CredentialItem item : items) { + if (item instanceof CredentialItem.Username) { + ((CredentialItem.Username) item).setValue(username); + continue; + } + if (item instanceof CredentialItem.StringType) { + ((CredentialItem.StringType) item).setValue(passphrase); + } + } + return true; + } + }; + UserInfo userInfo = new CredentialsProviderUserInfo(session, provider); + session.setUserInfo(userInfo); + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_git_clone.xml b/app/src/main/res/layout/activity_git_clone.xml index 07d57934..d53a2201 100644 --- a/app/src/main/res/layout/activity_git_clone.xml +++ b/app/src/main/res/layout/activity_git_clone.xml @@ -6,7 +6,7 @@ android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" - tools:context="com.zeapo.pwdstore.git.GitHandler" + tools:context="com.zeapo.pwdstore.git.GitActivity" android:background="@android:color/white"> + tools:context="com.zeapo.pwdstore.git.GitActivity" > Running command... Internal exception occurred - Message from jgit: /n + Message from jgit: \n You are about to use a read-only repository, you will not be able to push to it -- cgit v1.2.3 From d29f308848d4ad5ae277e3d8c032fab0a0ee7401 Mon Sep 17 00:00:00 2001 From: zeapo Date: Wed, 17 Dec 2014 23:32:35 +0100 Subject: add documentation --- app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java index 0445b114..3c5c20c6 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java @@ -46,6 +46,13 @@ public class CloneOperation extends GitOperation { return this; } + /** + * sets the authentication for the ssh-key scheme + * @param sshKey the ssh-key file + * @param username the username + * @param passphrase the passphrase + * @return the current object + */ @Override public CloneOperation setAuthentication(File sshKey, String username, String passphrase) { super.setAuthentication(sshKey, username, passphrase); -- cgit v1.2.3 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 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 From dbbb2305f739c70144ed1cb593837af54a1d893d Mon Sep 17 00:00:00 2001 From: zeapo Date: Wed, 17 Dec 2014 23:42:05 +0100 Subject: DRY refactoring --- .../java/com/zeapo/pwdstore/git/GitActivity.java | 42 +++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) 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 b841a42a..36fb96ad 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -11,6 +11,7 @@ import android.preference.PreferenceManager; import android.support.v7.app.ActionBarActivity; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -38,6 +39,7 @@ import java.util.regex.Pattern; // TODO move the messages to strings.xml public class GitActivity extends ActionBarActivity { + private static final String TAG = "GitAct"; private Activity activity; private Context context; @@ -604,33 +606,31 @@ public class GitActivity extends ActionBarActivity { } if (resultCode == RESULT_OK) { + GitOperation op; switch (requestCode) { case REQUEST_PULL: - 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(); - } + op = new PullOperation(localDir, activity).setCommand(hostname); break; + case REQUEST_PUSH: - 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; + op = new PushOperation(localDir, activity).setCommand(hostname); + break; + case GitOperation.GET_SSH_KEY_FROM_CLONE: - try { - new CloneOperation(localDir, activity) - .setCommand(hostname) - .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); - } catch (Exception e) { - e.printStackTrace(); - } + op = new CloneOperation(localDir, activity).setCommand(hostname); + break; + default: + Log.e(TAG, "Operation not recognized : " + resultCode); + setResult(RESULT_CANCELED); + finish(); + return; + } + + try { + op.executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + } catch (Exception e) { + e.printStackTrace(); } } -- cgit v1.2.3 From 88a6876238ecfff3926a5e4ba79b79bd6c2f7faa Mon Sep 17 00:00:00 2001 From: zeapo Date: Wed, 17 Dec 2014 23:55:42 +0100 Subject: more DRYness --- .../java/com/zeapo/pwdstore/git/GitActivity.java | 130 ++++++++------------- 1 file changed, 51 insertions(+), 79 deletions(-) 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 36fb96ad..c777d8f2 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -386,6 +386,32 @@ public class GitActivity extends ActionBarActivity { return super.onOptionsItemSelected(item); } + /** + * Saves the configuration found in the form + */ + private void saveConfiguration() { + // remember the settings + SharedPreferences.Editor editor = settings.edit(); + + editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); + editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); + editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); + editor.putString("git_remote_protocol", protocol); + editor.putString("git_remote_auth", connectionMode); + editor.putString("git_remote_port", port); + editor.commit(); + } + + /** + * Save the repository information to the shared preferences settings + * + * @param view + */ + public void saveConfiguration(View view) { + saveConfiguration(); + PasswordRepository.addRemote("origin", ((EditText) findViewById(R.id.clone_uri)).getText().toString(), true); + } + /** * Clones the repository, the directory exists, deletes it * @@ -427,7 +453,6 @@ public class GitActivity extends ActionBarActivity { username = hostname.split("@")[0]; } - if (localDir.exists()) { new AlertDialog.Builder(this). setTitle(R.string.dialog_delete_title). @@ -468,6 +493,8 @@ public class GitActivity extends ActionBarActivity { ). show(); } else { + saveConfiguration(); + try { new CloneOperation(localDir, activity) .setCommand(hostname) @@ -476,54 +503,28 @@ public class GitActivity extends ActionBarActivity { //This is what happens when jgit fails :( //TODO Handle the diffent cases of exceptions e.printStackTrace(); - } - } + } } } - /** - * Save the repository information to the shared preferences settings - * - * @param view + * Pull the latest changes from the remote repository and merges them locally */ - public void saveConfiguration(View view) { - // remember the settings - SharedPreferences.Editor editor = settings.edit(); - - editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); - editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); - editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); - editor.putString("git_remote_protocol", protocol); - editor.putString("git_remote_auth", connectionMode); - editor.putString("git_remote_port", port); - editor.commit(); - - PasswordRepository.addRemote("origin", ((EditText) findViewById(R.id.clone_uri)).getText().toString(), true); + public void pullFromRepository() { + syncRepository(REQUEST_PULL); } - public void cloneOperation(UsernamePasswordCredentialsProvider provider) { - - // remember the settings - SharedPreferences.Editor editor = settings.edit(); - - editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); - editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); - editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); - editor.putString("git_remote_protocol", protocol); - editor.putString("git_remote_auth", connectionMode); - editor.putString("git_remote_port", port); - editor.commit(); - - CloneCommand cmd = Git.cloneRepository(). - setCredentialsProvider(provider). - setCloneAllBranches(true). - setDirectory(localDir). - setURI(hostname); - - new GitAsyncTask(activity, true, false, CloneCommand.class).execute(cmd); + /** + * Pushes the latest changes from the local repository to the remote one + */ + public void pushToRepository() { + syncRepository(REQUEST_PUSH); } - public void pullFromRepository() { + /** + * Syncs the local repository with the remote one (either pull or push) + * @param operation the operation to execute can be REQUEST_PULL or REQUEST_PUSH + */ + private void syncRepository(int operation) { if (settings.getString("git_remote_username", "").isEmpty() || settings.getString("git_remote_server", "").isEmpty() || settings.getString("git_remote_location", "").isEmpty()) @@ -549,48 +550,19 @@ public class GitActivity extends ActionBarActivity { else { // check that the remote origin is here, else add it PasswordRepository.addRemote("origin", hostname, false); + GitOperation op; - 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(); + if (operation == REQUEST_PULL) { + op = new PullOperation(localDir, activity).setCommand(hostname); + } else if (operation == REQUEST_PUSH) { + op = new PushOperation(localDir, activity).setCommand(hostname); + } else { + Log.e(TAG, "Sync operation not recognized : " + operation); + return; } - } - } - - 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()) - 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() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - Intent intent = new Intent(activity, UserPreference.class); - startActivityForResult(intent, REQUEST_PUSH); - } - }) - .setNegativeButton("Nah... later", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - // do nothing :( - setResult(RESULT_OK); - finish(); - } - }) - .show(); - - else { - // check that the remote origin is here, else add it - PasswordRepository.addRemote("origin", hostname, false); try { - new PushOperation(localDir, activity) - .setCommand(hostname) - .executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); + op.executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key")); } catch (Exception e) { e.printStackTrace(); } -- cgit v1.2.3 From 6d898ddf886ce0d6617c384544bfe24d46dfe3e8 Mon Sep 17 00:00:00 2001 From: zeapo Date: Thu, 18 Dec 2014 21:28:01 +0100 Subject: remember the connection mode and the auth mode --- .../main/java/com/zeapo/pwdstore/git/GitActivity.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) 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 c777d8f2..551f17e3 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -83,7 +83,6 @@ public class GitActivity extends ActionBarActivity { final Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol); final Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode); - // init the spinner for connection modes final ArrayAdapter connection_mode_adapter = ArrayAdapter.createFromResource(this, R.array.connection_modes, android.R.layout.simple_spinner_item); @@ -103,6 +102,13 @@ public class GitActivity extends ActionBarActivity { } }); + + if (protocol.equals("ssh://")) { + protcol_spinner.setSelection(0); + } else { + protcol_spinner.setSelection(1); + } + // init the spinner for protocols ArrayAdapter protocol_adapter = ArrayAdapter.createFromResource(this, R.array.clone_protocols, android.R.layout.simple_spinner_item); @@ -139,6 +145,11 @@ public class GitActivity extends ActionBarActivity { } ); + if (connectionMode.equals("ssh-key")) { + protcol_spinner.setSelection(0); + } else { + protcol_spinner.setSelection(1); + } // init the server information final EditText server_url = ((EditText) findViewById(R.id.server_url)); @@ -503,7 +514,8 @@ public class GitActivity extends ActionBarActivity { //This is what happens when jgit fails :( //TODO Handle the diffent cases of exceptions e.printStackTrace(); - } } + } + } } /** -- cgit v1.2.3 From 530453025c1b0b90eb559e5480d57584b94ba661 Mon Sep 17 00:00:00 2001 From: zeapo Date: Thu, 18 Dec 2014 21:51:09 +0100 Subject: correct a typo for saved protocol/authmode --- .../main/java/com/zeapo/pwdstore/git/GitActivity.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 551f17e3..5bb44b32 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -102,13 +102,6 @@ public class GitActivity extends ActionBarActivity { } }); - - if (protocol.equals("ssh://")) { - protcol_spinner.setSelection(0); - } else { - protcol_spinner.setSelection(1); - } - // init the spinner for protocols ArrayAdapter protocol_adapter = ArrayAdapter.createFromResource(this, R.array.clone_protocols, android.R.layout.simple_spinner_item); @@ -145,12 +138,18 @@ public class GitActivity extends ActionBarActivity { } ); - if (connectionMode.equals("ssh-key")) { + if (protocol.equals("ssh://")) { protcol_spinner.setSelection(0); } else { protcol_spinner.setSelection(1); } + if (connectionMode.equals("ssh-key")) { + connection_mode_spinner.setSelection(0); + } else { + connection_mode_spinner.setSelection(1); + } + // init the server information final EditText server_url = ((EditText) findViewById(R.id.server_url)); final EditText server_port = ((EditText) findViewById(R.id.server_port)); @@ -255,6 +254,7 @@ public class GitActivity extends ActionBarActivity { findViewById(R.id.save_button).setVisibility(View.INVISIBLE); } + updateURI(); break; case REQUEST_PULL: -- cgit v1.2.3 From 3ca806d699182f3233c2425bd407988540083758 Mon Sep 17 00:00:00 2001 From: zeapo Date: Thu, 18 Dec 2014 21:52:38 +0100 Subject: set credential after they've been intialized --- .../main/java/com/zeapo/pwdstore/git/CloneOperation.java | 10 ++++++++-- app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java | 4 +--- .../main/java/com/zeapo/pwdstore/git/PullOperation.java | 14 ++++++++++---- .../main/java/com/zeapo/pwdstore/git/PushOperation.java | 12 ++++++++++-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java index 3c5c20c6..dc94ce3b 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java @@ -4,7 +4,6 @@ import android.app.Activity; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import java.io.File; @@ -27,7 +26,6 @@ public class CloneOperation extends GitOperation { */ public CloneOperation setCommand(String uri) { this.command = Git.cloneRepository(). - setCredentialsProvider(provider). setCloneAllBranches(true). setDirectory(repository.getWorkTree()). setURI(uri); @@ -58,4 +56,12 @@ public class CloneOperation extends GitOperation { super.setAuthentication(sshKey, username, passphrase); return this; } + + @Override + public void execute() throws Exception { + if (this.provider != null) { + ((CloneCommand) this.command).setCredentialsProvider(this.provider); + } + new GitAsyncTask(callingActivity, true, false, CloneCommand.class).execute(this.command); + } } 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 65436969..60112c90 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java @@ -78,9 +78,7 @@ public abstract class GitOperation { * * @throws Exception */ - public void execute() throws Exception { - new GitAsyncTask(callingActivity, true, false, GitCommand.class).execute(command); - } + public abstract void execute() throws Exception; /** * Executes the GitCommand in an async task after creating the authentication diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java index 0d43216d..2d499b4e 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java @@ -2,9 +2,8 @@ package com.zeapo.pwdstore.git; import android.app.Activity; -import com.zeapo.pwdstore.utils.PasswordRepository; - import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.PullCommand; import java.io.File; @@ -29,8 +28,15 @@ public class PullOperation extends GitOperation { this.command = new Git(repository) .pull() .setRebase(true) - .setRemote("origin") - .setCredentialsProvider(provider); + .setRemote("origin"); return this; } + + @Override + public void execute() throws Exception { + if (this.provider != null) { + ((PullCommand) this.command).setCredentialsProvider(this.provider); + } + new GitAsyncTask(callingActivity, true, false, PullCommand.class).execute(this.command); + } } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java index fa3e4dd9..fd4fb229 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java @@ -3,6 +3,7 @@ package com.zeapo.pwdstore.git; import android.app.Activity; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.PushCommand; import java.io.File; @@ -27,8 +28,15 @@ public class PushOperation extends GitOperation { this.command = new Git(repository) .push() .setPushAll() - .setRemote("origin") - .setCredentialsProvider(provider); + .setRemote("origin"); return this; } + + @Override + public void execute() throws Exception { + if (this.provider != null) { + ((PushCommand) this.command).setCredentialsProvider(this.provider); + } + new GitAsyncTask(callingActivity, true, false, PushCommand.class).execute(this.command); + } } -- cgit v1.2.3 From 78a2494d5e6fc2e479a5a4d98891d5ee1e04aeeb Mon Sep 17 00:00:00 2001 From: zeapo Date: Thu, 18 Dec 2014 23:35:36 +0100 Subject: starting to write tests --- .../java/com/zeapo/pwdstore/ApplicationTest.java | 13 ---- .../java/com/zeapo/pwdstore/GitActivityTest.java | 74 ++++++++++++++++++++++ 2 files changed, 74 insertions(+), 13 deletions(-) delete mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/ApplicationTest.java create mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/GitActivityTest.java diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/ApplicationTest.java b/app/src/androidTest/java/com/zeapo/pwdstore/ApplicationTest.java deleted file mode 100644 index e0cf8c74..00000000 --- a/app/src/androidTest/java/com/zeapo/pwdstore/ApplicationTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.zeapo.pwdstore; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityTest.java b/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityTest.java new file mode 100644 index 00000000..83995b51 --- /dev/null +++ b/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityTest.java @@ -0,0 +1,74 @@ +package com.zeapo.pwdstore; + +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.test.ActivityInstrumentationTestCase2; +import android.test.ActivityTestCase; +import android.test.InstrumentationTestCase; +import android.util.Log; +import android.widget.EditText; +import android.widget.Spinner; + +import com.zeapo.pwdstore.git.GitActivity; + +public class GitActivityTest extends ActivityInstrumentationTestCase2 { + private Activity gitActivity; + private Instrumentation mInstrumentation; + private SharedPreferences settings; + + private Spinner protocolSpinner; + private Spinner connectionModeSpinner; + private EditText uri; + private EditText server_url; + private EditText server_port; + private EditText server_path; + private EditText server_user; + + public GitActivityTest() { + super(GitActivity.class); + } + + protected void setUp() throws Exception { + super.setUp(); + mInstrumentation = getInstrumentation(); + + Intent intent = new Intent(); + intent.putExtra("Operation", GitActivity.EDIT_SERVER); + setActivityIntent(intent); + + gitActivity = getActivity(); // get a references to the app under test + assertNotNull(gitActivity); + + settings = PreferenceManager.getDefaultSharedPreferences(gitActivity.getApplicationContext()); + + uri = (EditText) gitActivity.findViewById(R.id.clone_uri); + server_url = ((EditText) gitActivity.findViewById(R.id.server_url)); + server_port = ((EditText) gitActivity.findViewById(R.id.server_port)); + server_path = ((EditText) gitActivity.findViewById(R.id.server_path)); + server_user = ((EditText) gitActivity.findViewById(R.id.server_user)); + protocolSpinner = (Spinner) gitActivity.findViewById(R.id.clone_protocol); + connectionModeSpinner = (Spinner) gitActivity.findViewById(R.id.connection_mode); + + assertEquals(protocolSpinner.getSelectedItem(), settings.getString("git_remote_protocol", "ssh://")); + assertEquals(connectionModeSpinner.getSelectedItem(), settings.getString("git_remote_auth", "ssh-key")); + } + + /** + * If we change from ssh protocol to https we automatically switch to username/password auth + * @throws Exception + */ + public void testSpinnerChange() throws Exception{ + gitActivity.runOnUiThread(new Runnable() { + public void run() { + protocolSpinner.requestFocus(); + protocolSpinner.setSelection(1); // 1 < is https:// + } + }); + mInstrumentation.waitForIdleSync(); + + assertEquals(connectionModeSpinner.getSelectedItem(), "username/password"); // 1 < is username/password + } +} -- cgit v1.2.3 From e170ef281b4d8f9b4c49d41faa077b06b1c9a84a Mon Sep 17 00:00:00 2001 From: zeapo Date: Sun, 4 Jan 2015 16:27:26 +0100 Subject: uri is useless here --- app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java | 10 +++++----- app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java | 5 ++--- app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java | 5 ++--- 3 files changed, 9 insertions(+), 11 deletions(-) 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 5bb44b32..6307fd0d 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -464,7 +464,7 @@ public class GitActivity extends ActionBarActivity { username = hostname.split("@")[0]; } - if (localDir.exists()) { + if (localDir.exists() && localDir.listFiles().length != 0) { new AlertDialog.Builder(this). setTitle(R.string.dialog_delete_title). setMessage(R.string.dialog_delete_msg). @@ -565,9 +565,9 @@ public class GitActivity extends ActionBarActivity { GitOperation op; if (operation == REQUEST_PULL) { - op = new PullOperation(localDir, activity).setCommand(hostname); + op = new PullOperation(localDir, activity).setCommand(); } else if (operation == REQUEST_PUSH) { - op = new PushOperation(localDir, activity).setCommand(hostname); + op = new PushOperation(localDir, activity).setCommand(); } else { Log.e(TAG, "Sync operation not recognized : " + operation); return; @@ -594,11 +594,11 @@ public class GitActivity extends ActionBarActivity { switch (requestCode) { case REQUEST_PULL: - op = new PullOperation(localDir, activity).setCommand(hostname); + op = new PullOperation(localDir, activity).setCommand(); break; case REQUEST_PUSH: - op = new PushOperation(localDir, activity).setCommand(hostname); + op = new PushOperation(localDir, activity).setCommand(); break; case GitOperation.GET_SSH_KEY_FROM_CLONE: diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java index 2d499b4e..abf4bfe6 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java @@ -20,11 +20,10 @@ public class PullOperation extends GitOperation { } /** - * Sets the command using the repository uri - * @param uri the uri of the repository + * Sets the command * @return the current object */ - public PullOperation setCommand(String uri) { + public PullOperation setCommand() { this.command = new Git(repository) .pull() .setRebase(true) diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java index fd4fb229..73ed05ff 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java @@ -20,11 +20,10 @@ public class PushOperation extends GitOperation { } /** - * Sets the command using the repository uri - * @param uri the uri of the repository + * Sets the command * @return the current object */ - public PushOperation setCommand(String uri) { + public PushOperation setCommand() { this.command = new Git(repository) .push() .setPushAll() -- cgit v1.2.3 From d5e124308e4ce1a894a0108d9ea716250ac55359 Mon Sep 17 00:00:00 2001 From: zeapo Date: Sun, 4 Jan 2015 16:27:56 +0100 Subject: test for clone ssh + user/pwd --- app/build.gradle | 1 + .../java/com/zeapo/pwdstore/GitActivityClone.java | 112 +++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java diff --git a/app/build.gradle b/app/build.gradle index 6e107b6e..4ec80f82 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -32,6 +32,7 @@ dependencies { compile project(':libraries:openpgp-api-lib') compile 'org.eclipse.jgit:org.eclipse.jgit:3.6.0.201411121045-m1' compile 'org.apache.commons:commons-io:1.3.2' + compile 'com.jayway.android.robotium:robotium-solo:5.2.1' } tasks.findAll { // make all tasks whose name starts with 'assemble'... it.name.startsWith 'assemble' diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java b/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java new file mode 100644 index 00000000..efe67d8b --- /dev/null +++ b/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java @@ -0,0 +1,112 @@ +package com.zeapo.pwdstore; + +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Spinner; + +import com.robotium.solo.Solo; +import com.zeapo.pwdstore.git.GitActivity; +import com.zeapo.pwdstore.utils.PasswordRepository; + +import org.apache.commons.io.FileUtils; + +import java.io.File; + +public class GitActivityClone extends ActivityInstrumentationTestCase2 { + private static final String TAG = "GitActTest"; + private Activity gitActivity; + private Instrumentation mInstrumentation; + private SharedPreferences settings; + + private Spinner protocolSpinner; + private Spinner connectionModeSpinner; + private EditText uri; + private EditText server_url; + private EditText server_port; + private EditText server_path; + private EditText server_user; + + public GitActivityClone() { + super(GitActivity.class); + } + + protected void setUp() throws Exception { + super.setUp(); + mInstrumentation = getInstrumentation(); + + Intent intent = new Intent(); + intent.putExtra("Operation", GitActivity.REQUEST_CLONE); + setActivityIntent(intent); + + gitActivity = getActivity(); // get a references to the app under test + assertNotNull(gitActivity); + + settings = PreferenceManager.getDefaultSharedPreferences(gitActivity.getApplicationContext()); + + uri = (EditText) gitActivity.findViewById(R.id.clone_uri); + server_url = ((EditText) gitActivity.findViewById(R.id.server_url)); + server_port = ((EditText) gitActivity.findViewById(R.id.server_port)); + server_path = ((EditText) gitActivity.findViewById(R.id.server_path)); + server_user = ((EditText) gitActivity.findViewById(R.id.server_user)); + protocolSpinner = (Spinner) gitActivity.findViewById(R.id.clone_protocol); + connectionModeSpinner = (Spinner) gitActivity.findViewById(R.id.connection_mode); + + assertNotNull(uri); + assertNotNull(server_url); + assertNotNull(server_port); + assertNotNull(server_path); + assertNotNull(server_user); + assertNotNull(protocolSpinner); + assertNotNull(connectionModeSpinner); + + assertEquals(protocolSpinner.getSelectedItem(), settings.getString("git_remote_protocol", "ssh://")); + assertEquals(connectionModeSpinner.getSelectedItem(), settings.getString("git_remote_auth", "ssh-key")); + } + + public void testCloneSshUser() throws Exception { + final Solo solo = new Solo(getInstrumentation(), getActivity()); + FileUtils.deleteDirectory(new File(gitActivity.getFilesDir() + gitActivity.getResources().getString(R.string.store_git))); + // create the repository static variable in PasswordRepository + PasswordRepository.getRepository(new File(gitActivity.getFilesDir() + gitActivity.getResources().getString(R.string.store_git))); + + gitActivity.runOnUiThread(new Runnable() { + public void run() { + protocolSpinner.setSelection(0); // ssh:// + connectionModeSpinner.setSelection(1); // user/pwd + } + }); + + mInstrumentation.waitForIdleSync(); + + solo.clearEditText(server_user); + solo.enterText(server_user, "testpwd"); + solo.clearEditText(server_path); + solo.enterText(server_path, "repo-test"); + solo.clearEditText(server_url); + solo.enterText(server_url, "192.168.1.28"); + + + mInstrumentation.waitForIdleSync(); + + gitActivity.runOnUiThread(new Runnable() { + public void run() { + ((Button) gitActivity.findViewById(R.id.clone_button)).performClick(); + } + }); + + mInstrumentation.waitForIdleSync(); + + assertTrue("Could not find the dialog!", solo.searchText(gitActivity.getResources().getString(R.string.passphrase_dialog_title))); + solo.enterText(solo.getEditText("Password"), "test"); + solo.clickOnButton(gitActivity.getResources().getString(R.string.dialog_ok)); + + mInstrumentation.waitForIdleSync(); + } +} -- cgit v1.2.3 From 1c2b000847b73c482154f5ccc15cf2cfb9865c4d Mon Sep 17 00:00:00 2001 From: zeapo Date: Sun, 4 Jan 2015 18:58:59 +0100 Subject: some tweak, and forgot strings --- app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java | 3 +-- app/src/main/java/com/zeapo/pwdstore/UserPreference.java | 3 ++- app/src/main/res/values/strings.xml | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java b/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java index efe67d8b..10d33472 100644 --- a/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java +++ b/app/src/androidTest/java/com/zeapo/pwdstore/GitActivityClone.java @@ -79,7 +79,6 @@ public class GitActivityClone extends ActivityInstrumentationTestCase2Set the time you want the password to be in clipboard Automatically Copy Password Automatically copy the password to the clipboard after decryption was successful. + SSH-key imported Error while trying to import the ssh-key Message : \n Recursive filtering -- cgit v1.2.3 From 6922652173e05433bb9524b036baafb96c91ca1b Mon Sep 17 00:00:00 2001 From: zeapo Date: Sun, 4 Jan 2015 21:47:38 +0100 Subject: set title when cloning/editing the server info --- app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java | 1 + app/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 6307fd0d..637d2052 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -79,6 +79,7 @@ public class GitActivity extends ActionBarActivity { case REQUEST_CLONE: case EDIT_SERVER: setContentView(R.layout.activity_git_clone); + setTitle(R.string.title_activity_git_clone); final Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol); final Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1d5ac4a5..8cf8d140 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,7 +12,7 @@ Target directory already exist. Current version support only a single store. Do you want to delete the current password store directory? Delete directory Cancel - Clone repository + Repository information Please clone or create a new repository below before trying to add a password or any synchronization operation. -- cgit v1.2.3