Skip to content

An easy way to upload the same filename to GitHub #582

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

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
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
20 changes: 18 additions & 2 deletions app/src/main/java/net/osmtracker/activity/GitHubUpload.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
import net.osmtracker.GitHubUser;
import net.osmtracker.R;
import net.osmtracker.db.DbGitHubUser;
import net.osmtracker.util.Callback;
import net.osmtracker.util.DialogUtils;
import net.osmtracker.util.GitHubUtils;

import org.json.JSONArray;
import org.json.JSONException;
Expand Down Expand Up @@ -106,7 +108,22 @@ private void uploadCommit() {
}
}

startUploadGitHub(encondedFile.toString(), file.getName(), commitMsj);
String repoOwner = getRepoName().substring(0, getRepoName().indexOf("/")).replace(".base64", "");
String repoName = getRepoName().substring(getRepoName().indexOf("/") + 1);
String repoFilePath = file.getName().replace(".base64", "");
GitHubUtils.getGHFilenameAsync(repoOwner, repoName, repoFilePath, gitHubUser.getToken(),
new Callback() {
@Override
public String onResult(String result) {
if (result != null) {
System.out.println("uploading to GitHub: " + result);
startUploadGitHub(encondedFile.toString(), result, commitMsj);
} else {
System.out.println("Error while getting filename.");
}
return result;
}
});
} catch (IOException e) {
Toast.makeText(GitHubUpload.this, R.string.gpx_file_read_error, Toast.LENGTH_SHORT).show();
e.printStackTrace();
Expand Down Expand Up @@ -151,7 +168,6 @@ private void openActivityOnClick(int btnId, Class<? extends Activity> destinatio
* Either starts uploading directly if we are authenticated against GitHub
*/
private void startUploadGitHub(final String fileInBase64, String filename, String commitMsj){
filename = filename.substring(0, filename.lastIndexOf("."));
String fullURL = getBaseURL()+"/repos/"+getRepoName()+"/contents/"+filename;

ProgressDialog progressDialog = new ProgressDialog(this);
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/java/net/osmtracker/util/Callback.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package net.osmtracker.util;

/**
* A generic callback interface used for asynchronous operations.
* Implementations of this interface should define how to handle the result
* of an asynchronous task.
*/
public interface Callback {
/**
* Called when the asynchronous operation is completed.
* Implementations should handle the provided result accordingly.
*
* @param result The result of the operation, which may be {@code null} if an error occurs.
* @return A string value that may be used by the calling function, if applicable.
*/
String onResult(String result);
}
125 changes: 125 additions & 0 deletions app/src/main/java/net/osmtracker/util/GitHubUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package net.osmtracker.util;

import android.os.AsyncTask;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
* Utility class for interacting with the GitHub API.
* Provides methods to retrieve file information and manage file uploads.
*
* <p>This class includes methods to:
* <ul>
* <li>Generate a unique filename within a GitHub repository.</li>
* <li>Retrieve the SHA hash of a file stored in a GitHub repository.</li>
* </ul>
* </p>
*
* <p>It requires a valid GitHub authentication token for API requests.</p>
*/
public class GitHubUtils {
/**
* Retrieves the SHA hash of a file in a GitHub repository.
* If the file does not exist, it returns {@code null}.
*
* @param repoOwner The owner of the repository (user or organization).
* @param repoName The name of the GitHub repository.
* @param repoFilePath The file path in the repository.
* @param token The GitHub authentication token with appropriate permissions.
* @return The SHA hash of the file if it exists, or {@code null} if the file is not found.
* @throws IOException If an I/O error occurs while making the request.
* @throws JSONException If an error occurs while parsing the JSON response.
*/
public static void getFileSHAAsync(String repoOwner, String repoName, String repoFilePath, String token, Callback callback) {
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... voids) {
try {
String apiUrl = "https://api.github.com/repos/" + repoOwner + "/" + repoName + "/contents/" + repoFilePath;
System.out.println("Fetching SHA: " + apiUrl);
HttpURLConnection connection = (HttpURLConnection) new URL(apiUrl).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + token);
connection.setRequestProperty("Accept", "application/vnd.github.v3+json");

if (connection.getResponseCode() == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
JSONObject jsonResponse = new JSONObject(response.toString());
return jsonResponse.getString("sha");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(String sha) {
callback.onResult(sha); // Return result via callback
}
}.execute();
}

/**
* Asynchronously generates a unique filename in a GitHub repository.
* If the file already exists, a number is appended before the extension.
*
* @param repoOwner The owner of the repository.
* @param repoName The name of the GitHub repository.
* @param repoFilePath The initial file path in the repository.
* @param token The GitHub authentication token.
* @param callback Callback to return the generated filename.
*/
public static void getGHFilenameAsync(String repoOwner, String repoName, final String repoFilePath, String token, Callback callback) {
String filename = repoFilePath.substring(0, repoFilePath.lastIndexOf("."));
String extension = repoFilePath.substring(repoFilePath.lastIndexOf("."));
checkFileExists(repoOwner, repoName, filename, extension, 0, token, callback);
}

/**
* Recursively checks if a file exists and generates a unique filename.
*
* @param repoOwner The owner of the repository.
* @param repoName The GitHub repository name.
* @param filename The base filename (without extension).
* @param extension The file extension.
* @param count The current attempt number for uniqueness.
* @param token The GitHub authentication token.
* @param callback Callback to return the final unique filename.
*/
private static void checkFileExists(String repoOwner, String repoName, String filename, String extension, int count, String token, Callback callback) {
String newFilename;// (count == 0) ? filename + extension : filename + "(" + count + ")" + extension;
if (count == 0) {
newFilename = filename + extension;
} else {
newFilename = filename + "(" + count + ")" + extension;
}

getFileSHAAsync(repoOwner, repoName, newFilename, token, new Callback() {
@Override
public String onResult(String sha) {
if (sha == null) {
// File does not exist, return the new unique filename
callback.onResult(newFilename);
} else {
// File exists, recursively try with the next count
checkFileExists(repoOwner, repoName, filename, extension, count + 1, token, callback);
}
return null;
}
});
}
}
50 changes: 1 addition & 49 deletions app/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
<string name="trackmgr_contextmenu_export">Exportar como GPX</string>
<string name="trackmgr_contextmenu_share">Compartir GPX</string>
<string name="trackmgr_contextmenu_osm_upload">Subir a OpenStreetMap</string>
<string name="trackmgr_contextmenu_github_upload">Subir a GitHub</string>
<string name="trackmgr_contextmenu_display">Visualizar</string>
<string name="trackmgr_contextmenu_details">Detalles</string>
<string name="trackmgr_contextmenu_title">Traza #{0}</string>
Expand Down Expand Up @@ -175,53 +174,6 @@
<string name="github_repository_settings_valid_server">Repositorio de GitHub válido</string>
<string name="github_repository_settings_invalid_server">Repositorio de GitHub inválido</string>

<!-- Upload to GitHub functionality-->
<string name="successfully_created">Creado exitosamente</string>
<string name="error_creating">Error al crear</string>
<string name="db_error">Error en base de datos</string>
<string name="successfully_saved">Guardado exitosamente</string>
<string name="saving_error">Error al guardar</string>
<string name="pr_status">Estado del pull request: </string>
<string name="repository_information_error">Error al obtener información del repositorio</string>
<string name="successfully_uploaded">Subido exitosamente</string>"
<string name="error_uploading">Error al subir</string>
<string name="gpx_file_read_error">Error al leer el archivo GPX</string>
<string name="gpx_file_not_found">No se encontró el archivo GPX</string>
<string name="uploading_file">Subiendo: </string>
<string name="item_selected">Selecciono el elemento: </string>
<string name="github_repository_private">Privado: </string>
<string name="github_no_repository_name">Indique el nombre del repositorio</string>
<string name="error_field_required">Campo requerido</string>
<!-- GitHubConfig -->
<string name="github_config_btn">Configurar</string>
<string name="github_token_placeholder">Token de GitHub:</string>
<string name="github_get_token_btn">Obtener token</string>
<string name="github_token_guide_title">Cómo obtener un token de GitHub:</string>
<string name="how_to_get_ghToken_guide_step_1">1. Haga clic en el botón para abrir el sitio web de GitHub y crear un token. Inicie sesión con su cuenta de GitHub si es necesario.</string>
<string name="how_to_get_ghToken_guide_step_2">2. Seleccione \"Tokens (Clásicos)\" y haga clic en el botón \"Generar nuevo token\".</string>
<string name="how_to_get_ghToken_guide_step_3">3. Asigne un nombre descriptivo a su token.</string>
<string name="how_to_get_ghToken_guide_step_4">4. Seleccione una fecha de expiración. Recomendamos \"Sin expiración\" para evitar repetir este paso.</string>
<string name="how_to_get_ghToken_guide_step_5">5. Seleccione los permisos que desee otorgar al token (OSMTracker solo necesita el permiso de repositorio).</string>
<string name="how_to_get_ghToken_guide_step_6">6. Haga clic en el botón \"Generar token\".</string>
<string name="how_to_get_ghToken_guide_step_7">7. Copie el token generado y péguelo en el campo \"Token de GitHub\".</string>
<string name="how_to_get_ghToken_guide_note">⚠️ Puede guardar en blanco para borrar sus credenciales.</string>
<!-- GitHubUpload -->
<string name="upload_to_github_description">Mensaje del commit:</string>
<string name="upload_to_github_create_fork">Crear\nfork</string>
<string name="upload_to_github_open_pull_request">Abrir pull request</string>
<string name="upload_to_github_select_repo">Seleccione un repositorio</string>
<string name="upload_to_github_create_repository">Crear repositorio</string>
<string name="upload_to_github_commit_btn">Hacer commit</string>
<string name="upload_to_github_configure">Configurar</string>
<!-- GitHubNewFork -->
<string name="upload_to_github_forked_repo_owner">Usuario del repositorio original</string>
<string name="upload_to_github_forked_repo_name">Nombre del repositorio original</string>
<string name="create">Crear</string>
<!-- GitHubPullRequest -->
<string name="upload_to_github_pr_title">Título del Pull Request</string>
<string name="upload_to_github_pr_description">Descripción del Pull Request</string>
<!-- END Upload to GitHub functionality-->

<!--App Introduction-->
<string name="app_intro">Introducción a OSMTracker para Android ™</string>
<!--Intro - slide1-->
Expand All @@ -231,4 +183,4 @@
<string name="app_intro_slide2_title">Feliz trazado 🗺 😎</string>
<string name="app_intro_slide2_description">OSMTracker para Android usará su ubicación GPS para registrar puntos de traza y puntos, incluso cuando la aplicación se está ejecutando en segundo plano.
Tus datos no se utilizan para respaldar anuncios.</string>
</resources>
</resources>
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@
<string name="repository_information_error">Error with repository information</string>
<string name="successfully_uploaded">Successfully uploaded</string>"
<string name="error_uploading">Error uploading</string>
<string name="uploading_file">Uploading file: </string>
<string name="gpx_file_read_error">Error reading the GPX file</string>
<string name="gpx_file_not_found">GPX file not found</string>
<string name="uploading_file">Uploading file: </string>
<string name="item_selected">Item Selected: </string>
<string name="github_repository_private">Private: </string>
<string name="github_no_repository_name">You must specify a repository name</string>
Expand Down