Skip to content
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
20 changes: 19 additions & 1 deletion app/src/main/java/net/osmtracker/activity/GitHubUpload.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
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 +109,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
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;
}
});
}
}
4 changes: 3 additions & 1 deletion app/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,11 @@
<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="uploading_file">Subiendo: </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>
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,11 @@
<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_creating_repository">Creating repository</string>
Expand Down