Merge pull request #57 from zeapo/feature/refactor-git
Refactoring of the git process
This commit is contained in:
commit
df8994d84f
17 changed files with 759 additions and 372 deletions
|
@ -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'
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
package com.zeapo.pwdstore;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
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<GitActivity> {
|
||||
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://
|
||||
}
|
||||
});
|
||||
|
||||
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() {
|
||||
connectionModeSpinner.setSelection(1); // user/pwd
|
||||
((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();
|
||||
}
|
||||
}
|
|
@ -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<GitActivity> {
|
||||
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
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".git.GitHandler"
|
||||
<activity android:name=".git.GitActivity"
|
||||
android:parentActivityName=".PasswordStore">
|
||||
<meta-data android:name="android.PARENT_ACTIVITY1"
|
||||
android:value="com.zeapo.pwdstore.PasswordStore" />
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@ import android.preference.PreferenceFragment;
|
|||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
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 +106,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;
|
||||
|
@ -153,7 +154,7 @@ public class UserPreference extends ActionBarActivity implements Preference.OnPr
|
|||
{
|
||||
try {
|
||||
copySshKey(data.getData());
|
||||
Log.i("PREF", "Got key");
|
||||
Toast.makeText(this, this.getResources().getString(R.string.ssh_key_success_dialog_title), Toast.LENGTH_LONG).show();
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} catch (IOException e)
|
||||
|
|
67
app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java
Normal file
67
app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
package com.zeapo.pwdstore.git;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
|
||||
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().
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -10,22 +10,17 @@ 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.util.Log;
|
||||
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;
|
||||
|
@ -34,29 +29,17 @@ 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 {
|
||||
public class GitActivity extends ActionBarActivity {
|
||||
private static final String TAG = "GitAct";
|
||||
|
||||
private Activity activity;
|
||||
private Context context;
|
||||
|
@ -77,8 +60,6 @@ public class GitHandler extends ActionBarActivity {
|
|||
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);
|
||||
|
@ -98,11 +79,11 @@ public class GitHandler 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);
|
||||
|
||||
|
||||
// init the spinner for connection modes
|
||||
final ArrayAdapter<CharSequence> connection_mode_adapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.connection_modes, android.R.layout.simple_spinner_item);
|
||||
|
@ -131,9 +112,9 @@ public class GitHandler 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 +122,7 @@ public class GitHandler 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);
|
||||
|
||||
|
@ -158,13 +139,24 @@ public class GitHandler extends ActionBarActivity {
|
|||
}
|
||||
);
|
||||
|
||||
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));
|
||||
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 +172,8 @@ public class GitHandler 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 +182,13 @@ public class GitHandler 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 +197,13 @@ public class GitHandler 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 +212,13 @@ public class GitHandler 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 +227,8 @@ public class GitHandler extends ActionBarActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) { }
|
||||
public void afterTextChanged(Editable editable) {
|
||||
}
|
||||
});
|
||||
|
||||
server_uri.addTextChangedListener(new TextWatcher() {
|
||||
|
@ -247,8 +247,7 @@ public class GitHandler 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 {
|
||||
|
@ -256,21 +255,24 @@ public class GitHandler extends ActionBarActivity {
|
|||
findViewById(R.id.save_button).setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
updateURI();
|
||||
|
||||
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 +280,9 @@ public class GitHandler 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 +306,7 @@ public class GitHandler 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 +324,15 @@ public class GitHandler 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));
|
||||
|
@ -397,76 +398,35 @@ public class GitHandler extends ActionBarActivity {
|
|||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
protected class GitConfigSessionFactory extends JschConfigSessionFactory {
|
||||
/**
|
||||
* Saves the configuration found in the form
|
||||
*/
|
||||
private void saveConfiguration() {
|
||||
// remember the settings
|
||||
SharedPreferences.Editor editor = settings.edit();
|
||||
|
||||
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;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param view
|
||||
*/
|
||||
public void cloneRepository(View view) {
|
||||
|
@ -505,8 +465,7 @@ public class GitHandler 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).
|
||||
|
@ -516,7 +475,15 @@ public class GitHandler 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();
|
||||
|
@ -538,8 +505,12 @@ public class GitHandler extends ActionBarActivity {
|
|||
).
|
||||
show();
|
||||
} else {
|
||||
saveConfiguration();
|
||||
|
||||
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
|
||||
|
@ -548,53 +519,28 @@ public class GitHandler extends ActionBarActivity {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the latest changes from the remote repository and merges them locally
|
||||
*/
|
||||
public void pullFromRepository() {
|
||||
syncRepository(REQUEST_PULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the repository information to the shared preferences settings
|
||||
* @param view
|
||||
* Pushes the latest changes from the local repository to the remote one
|
||||
*/
|
||||
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 pushToRepository() {
|
||||
syncRepository(REQUEST_PUSH);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
/**
|
||||
* 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() )
|
||||
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() {
|
||||
|
@ -616,185 +562,23 @@ public class GitHandler 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);
|
||||
PasswordRepository.addRemote("origin", hostname, false);
|
||||
GitOperation op;
|
||||
|
||||
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();
|
||||
if (operation == REQUEST_PULL) {
|
||||
op = new PullOperation(localDir, activity).setCommand();
|
||||
} else if (operation == REQUEST_PUSH) {
|
||||
op = new PushOperation(localDir, activity).setCommand();
|
||||
} 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();
|
||||
Log.e(TAG, "Sync operation not recognized : " + operation);
|
||||
return;
|
||||
}
|
||||
} 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();
|
||||
try {
|
||||
op.executeAfterAuthentication(connectionMode, settings.getString("git_remote_username", "git"), new File(getFilesDir() + "/.ssh_key"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -807,16 +591,31 @@ public class GitHandler extends ActionBarActivity {
|
|||
}
|
||||
|
||||
if (resultCode == RESULT_OK) {
|
||||
GitOperation op;
|
||||
|
||||
switch (requestCode) {
|
||||
case REQUEST_PULL:
|
||||
authenticateAndRun("pullOperation");
|
||||
op = new PullOperation(localDir, activity).setCommand();
|
||||
break;
|
||||
|
||||
case REQUEST_PUSH:
|
||||
authenticateAndRun("pushOperation");
|
||||
op = new PushOperation(localDir, activity).setCommand();
|
||||
break;
|
||||
case GET_SSH_KEY_FROM_CLONE:
|
||||
authenticateAndRun("cloneOperation");
|
||||
|
||||
case GitOperation.GET_SSH_KEY_FROM_CLONE:
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
170
app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java
Normal file
170
app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
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 abstract void execute() throws Exception;
|
||||
|
||||
/**
|
||||
* 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()) {
|
||||
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 {
|
||||
// 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);
|
||||
} 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) {
|
||||
try {
|
||||
// Authenticate using the ssh-key and then execute the command
|
||||
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) {
|
||||
// authenticate using the user/pwd and then execute the command
|
||||
try {
|
||||
setAuthentication(username, password.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();
|
||||
}
|
||||
}
|
||||
}
|
41
app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java
Normal file
41
app/src/main/java/com/zeapo/pwdstore/git/PullOperation.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
package com.zeapo.pwdstore.git;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.PullCommand;
|
||||
|
||||
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
|
||||
* @return the current object
|
||||
*/
|
||||
public PullOperation setCommand() {
|
||||
this.command = new Git(repository)
|
||||
.pull()
|
||||
.setRebase(true)
|
||||
.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);
|
||||
}
|
||||
}
|
41
app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java
Normal file
41
app/src/main/java/com/zeapo/pwdstore/git/PushOperation.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
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;
|
||||
|
||||
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
|
||||
* @return the current object
|
||||
*/
|
||||
public PushOperation setCommand() {
|
||||
this.command = new Git(repository)
|
||||
.push()
|
||||
.setPushAll()
|
||||
.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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:pwstore="http://schemas.android.com/apk/res-auto"
|
||||
tools:context="com.zeapo.pwdstore.git.GitHandler" >
|
||||
tools:context="com.zeapo.pwdstore.git.GitActivity" >
|
||||
<item android:id="@+id/user_pref"
|
||||
android:title="@string/action_settings"
|
||||
android:orderInCategory="100"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<string name="dialog_delete_msg">Target directory already exist. Current version support only a single store. Do you want to delete the current password store directory?</string>
|
||||
<string name="dialog_delete">Delete directory</string>
|
||||
<string name="dialog_do_not_delete">Cancel</string>
|
||||
<string name="title_activity_git_clone">Clone repository</string>
|
||||
<string name="title_activity_git_clone">Repository information</string>
|
||||
|
||||
<!-- Password Store -->
|
||||
<string name="creation_dialog_text">Please clone or create a new repository below before trying to add a password or any synchronization operation.</string>
|
||||
|
@ -41,7 +41,7 @@
|
|||
<!-- Git Async Task -->
|
||||
<string name="running_dialog_text">Running command...</string>
|
||||
<string name="jgit_error_dialog_title">Internal exception occurred</string>
|
||||
<string name="jgit_error_dialog_text">Message from jgit: /n</string>
|
||||
<string name="jgit_error_dialog_text">Message from jgit: \n</string>
|
||||
|
||||
<!-- Git Handler -->
|
||||
<string name="read_only_dialog_text">You are about to use a read-only repository, you will not be able to push to it</string>
|
||||
|
@ -108,6 +108,7 @@
|
|||
<string name="pref_password_dialog_title">Set the time you want the password to be in clipboard</string>
|
||||
<string name="pref_copy_title">Automatically Copy Password</string>
|
||||
<string name="pref_copy_dialog_title">Automatically copy the password to the clipboard after decryption was successful.</string>
|
||||
<string name="ssh_key_success_dialog_title" translatable="false">SSH-key imported</string>
|
||||
<string name="ssh_key_error_dialog_title">Error while trying to import the ssh-key</string>
|
||||
<string name="ssh_key_error_dialog_text">Message : \n</string>
|
||||
<string name="pref_recursive_filter">Recursive filtering</string>
|
||||
|
|
Loading…
Reference in a new issue