Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 21 git workdir in private storage #18

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<!-- For BroadcastReceiver below -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ public String getEmail() {
public String repositoryFilepath() {
return repoPreferences.getStringValueWithGlobalDefault(
R.string.pref_key_git_repository_filepath,
AppPreferences.repositoryStoragePathForUri(
repoPreferences.getContext(), remoteUri()));
AppPreferences.gitRepoStoragePathForRepoId(
repoPreferences.getContext(),
repoPreferences.getRepoId()));
}

@Override
Expand Down
24 changes: 2 additions & 22 deletions app/src/main/java/com/orgzly/android/prefs/AppPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -916,31 +916,11 @@ public static boolean gitIsEnabled(Context context) {
context.getResources().getString(R.string.pref_key_git_is_enabled),
context.getResources().getBoolean(R.bool.pref_default_git_is_enabled));
}

public static String defaultRepositoryStorageDirectory(Context context) {
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
return getStringFromSelector(
context, R.string.pref_key_git_default_repository_directory, path.toString());
}

public static String repositoryStoragePathForUri(Context context, Uri repoUri) {
String directoryFilename = repoUri.toString();
try {
directoryFilename = new URIish(directoryFilename).getPath();
} catch (URISyntaxException e) {
directoryFilename = directoryFilename.replaceAll("/[^A-Za-z0-9 ]/", "");
}
Uri baseUri = Uri.parse(defaultRepositoryStorageDirectory(context));
return baseUri.buildUpon().appendPath(directoryFilename).build().getPath();
}

private static String getStringFromSelector(Context context, int selector, String def) {
return getStateSharedPreferences(context).getString(getSelector(context, selector), def);
public static String gitRepoStoragePathForRepoId(Context context, Long repoId) {
return new File(context.getCacheDir(), "gitrepo" + repoId).getAbsolutePath();
}

private static String getSelector(Context context, int selector) {
return context.getResources().getString(selector);
}

/*
* Last used version.
Expand Down
10 changes: 2 additions & 8 deletions app/src/main/java/com/orgzly/android/repos/GitRepo.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,8 @@ private static Git verifyExistingRepo(File directoryFile) throws IOException {
*/
private static Git cloneRepo(Uri repoUri, File directoryFile, GitTransportSetter transportSetter,
ProgressMonitor pm) throws IOException {
if (!directoryFile.exists()) {
throw new IOException(String.format("The directory %s does not exist", directoryFile.toString()), new FileNotFoundException());
}

// Using list() can be resource intensive if there's many files, but since we just call it
// at the time of cloning once we should be fine for now
if (directoryFile.list().length != 0) {
throw new IOException(String.format("The directory must be empty"), new DirectoryNotEmpty(directoryFile));
if (!directoryFile.mkdir()) {
throw new IOException(String.format("Failed to create Git workdir %s", directoryFile));
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.orgzly.android.ui.SingleLiveEvent
import com.orgzly.android.usecase.RepoCreate
import com.orgzly.android.usecase.RepoUpdate
import com.orgzly.android.usecase.UseCase
import com.orgzly.android.usecase.UseCaseResult
import com.orgzly.android.usecase.UseCaseRunner

open class RepoViewModel(private val dataRepository: DataRepository, open var repoId: Long) : CommonViewModel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import android.net.Uri
import android.os.AsyncTask
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.text.TextUtils
import android.view.ContextMenu
Expand All @@ -31,18 +30,15 @@ import com.orgzly.android.prefs.RepoPreferences
import com.orgzly.android.repos.GitRepo
import com.orgzly.android.repos.RepoType
import com.orgzly.android.ui.CommonActivity
import com.orgzly.android.ui.repo.BrowserActivity
import com.orgzly.android.ui.repo.RepoViewModel
import com.orgzly.android.ui.repo.RepoViewModelFactory
import com.orgzly.android.ui.showSnackbar
import com.orgzly.android.util.AppPermissions
import com.orgzly.android.util.MiscUtils
import com.orgzly.databinding.ActivityRepoGitBinding
import org.eclipse.jgit.errors.TransportException
import org.eclipse.jgit.errors.NoRemoteRepositoryException
import org.eclipse.jgit.errors.NotSupportedException
import org.eclipse.jgit.lib.ProgressMonitor
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException

Expand All @@ -65,10 +61,6 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
setContentView(binding.root)

fields = arrayOf(
Field(
binding.activityRepoGitDirectory,
binding.activityRepoGitDirectoryLayout,
R.string.pref_key_git_repository_filepath),
Field(
binding.activityRepoGitHttpsUsername,
binding.activityRepoGitHttpsUsernameLayout,
Expand Down Expand Up @@ -100,10 +92,6 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
MiscUtils.clearErrorOnTextChange(it.editText, it.layout)
}

binding.activityRepoGitDirectoryBrowse.setOnClickListener {
startLocalFileBrowser(binding.activityRepoGitDirectory, ACTIVITY_REQUEST_CODE_FOR_DIRECTORY_SELECTION)
}

val repoId = intent.getLongExtra(ARG_REPO_ID, 0)

val factory = RepoViewModelFactory.getInstance(dataRepository, repoId)
Expand All @@ -118,7 +106,6 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
}
} else {
/* Set default values for new repo being added. */
createDefaultRepoFolder()
binding.activityRepoGitAuthor.setText("Orgzly")
binding.activityRepoGitBranch.setText(R.string.git_default_branch)
val userDeviceName: String = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S) {
Expand All @@ -131,9 +118,7 @@ class GitRepoActivity : CommonActivity(), GitPreferences {

viewModel.finishEvent.observeSingle(this, Observer {
saveToPreferences(viewModel.repoId)

// TODO: Check permission on start
runWithPermission(AppPermissions.Usage.LOCAL_REPO, Runnable { finish() })
finish()
})

viewModel.alreadyExistsEvent.observeSingle(this, Observer {
Expand Down Expand Up @@ -203,23 +188,6 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
}
}

// TODO: Since we can create multiple syncs, this folder might be re-used, do we want to create
// a new one if this directory is already used up?
private fun createDefaultRepoFolder() {
if (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED) {
return
}
val externalPath = Environment.getExternalStorageDirectory().path
val orgzlyGitPath = File("$externalPath/orgzly-git/")
var success = false
try {
success = orgzlyGitPath.mkdirs()
} catch(error: SecurityException) {}
if (success || (orgzlyGitPath.exists() && orgzlyGitPath.list().size == 0)) {
binding.activityRepoGitDirectory.setText(orgzlyGitPath.path)
}
}

private fun setFromPreferences() {
val prefs = RepoPreferences.fromId(this, viewModel.repoId, dataRepository)
for (field in fields) {
Expand Down Expand Up @@ -271,13 +239,9 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
if (repoId != 0L) {
save()
} else {
val targetDirectory = File(binding.activityRepoGitDirectory.text.toString())
if (targetDirectory.list()!!.isNotEmpty()) {
binding.activityRepoGitDirectoryLayout.error = getString(R.string.git_clone_error_target_not_empty)
} else {
// TODO: If this fails we should notify the user in a nice way and mark the git repo field as bad
RepoCloneTask(this).execute()
}
save() // Create the new repo in the database, so that viewModel knows its repoId.
// TODO: If this fails we should notify the user in a nice way and mark the git repo field as bad
RepoCloneTask(this).execute()
}
}
}
Expand Down Expand Up @@ -339,11 +303,6 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
hasEmptyFields = true
}

val targetDirectory = File(binding.activityRepoGitDirectory.text.toString())
if (!targetDirectory.exists()) {
binding.activityRepoGitDirectoryLayout.error = getString(R.string.git_clone_error_invalid_target_dir)
}

for (field in fields) {
if (field.layout.visibility == View.GONE || field.allowEmpty) {
continue;
Expand Down Expand Up @@ -398,12 +357,7 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
}

override fun repositoryFilepath(): String {
val v = binding.activityRepoGitDirectory.text.toString()
return if (v.isNotEmpty()) {
v
} else {
AppPreferences.repositoryStoragePathForUri(this, remoteUri())
}
return AppPreferences.gitRepoStoragePathForRepoId(this, viewModel.repoId)
}

override fun remoteName(): String {
Expand All @@ -420,34 +374,6 @@ class GitRepoActivity : CommonActivity(), GitPreferences {
return Uri.parse(remoteUriString)
}

private fun startLocalFileBrowser(editText: EditText, requestCode: Int, isFileSelectable: Boolean = false) {
val intent = Intent(Intent.ACTION_VIEW).setClass(this, BrowserActivity::class.java)

if (!TextUtils.isEmpty(editText.text)) {
val uri = editText.text.toString()
val path = Uri.parse(uri).path
intent.putExtra(BrowserActivity.ARG_STARTING_DIRECTORY, path)
}

if (isFileSelectable) {
intent.putExtra(BrowserActivity.ARG_IS_FILE_SELECTABLE, true)
}

startActivityForResult(intent, requestCode)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)

when (requestCode) {
ACTIVITY_REQUEST_CODE_FOR_DIRECTORY_SELECTION ->
if (resultCode == Activity.RESULT_OK && data != null) {
val uri = data.data
binding.activityRepoGitDirectory.setText(uri?.path)
}
}
}

internal inner class CloneProgressUpdate(var amount: Int, var setMax: Boolean)

internal inner class RepoCloneTask(var fragment: GitRepoActivity) : AsyncTask<Void, CloneProgressUpdate, IOException>(), ProgressMonitor {
Expand Down Expand Up @@ -517,8 +443,6 @@ class GitRepoActivity : CommonActivity(), GitPreferences {

private const val ARG_REPO_ID = "repo_id"

const val ACTIVITY_REQUEST_CODE_FOR_DIRECTORY_SELECTION = 0

@JvmStatic
@JvmOverloads
fun start(activity: Activity, repoId: Long = 0) {
Expand Down
15 changes: 3 additions & 12 deletions app/src/main/java/com/orgzly/android/ui/repos/ReposActivity.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package com.orgzly.android.ui.repos

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.view.ContextMenu
import android.view.MenuItem
import android.view.View
Expand All @@ -33,7 +29,6 @@ import com.orgzly.android.ui.showSnackbar
import com.orgzly.databinding.ActivityReposBinding
import javax.inject.Inject


/**
* List of user-configured repositories.
*/
Expand Down Expand Up @@ -225,18 +220,14 @@ class ReposActivity : CommonActivity(), AdapterView.OnItemClickListener, Activit
}

R.id.repos_options_menu_item_new_git -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
val uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID)
startActivity(
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri))
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
GitRepoActivity.start(this)
} else {
// TODO: Show explanation why possibly, if ActivityCompat.shouldShowRequestPermissionRationale() says so?
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
ACTIVITY_REQUEST_CODE_FOR_READ_WRITE_EXTERNAL_STORAGE)
} else {
GitRepoActivity.start(this)
}
return
}
Expand Down
32 changes: 0 additions & 32 deletions app/src/main/res/layout/activity_repo_git.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,38 +37,6 @@

</com.google.android.material.textfield.TextInputLayout>

<!-- Directory -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/space_between_content_areas"
android:orientation="horizontal">

<Button
android:id="@+id/activity_repo_git_directory_browse"
style="@style/Button.Repo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/screen_edge"
android:text="@string/browse" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/activity_repo_git_directory_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/activity_repo_git_directory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/git_directory_hint"
android:inputType="text" />

</com.google.android.material.textfield.TextInputLayout>

</LinearLayout>

<LinearLayout
android:id="@+id/activity_repo_git_https_auth_info"
android:layout_width="match_parent"
Expand Down