Skip to content

Commit

Permalink
feat(upload): Retrive an existing folder if any
Browse files Browse the repository at this point in the history
  • Loading branch information
rbioteau committed Jan 19, 2024
1 parent 8d0b978 commit 4a0d44a
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ work
.idea
.iml
.DS_Store
out
out
.vscode/
2 changes: 1 addition & 1 deletion gdrive-cli/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ To run debug mode on your IDE, add `--debug-jvm`

## How to upload folder

./gradlew run --args " -c path/credentialFile.json upload path/folderToUpload destinationFolderPath --renameTo newFolderName"
./gradlew run --args " -c path/credentialFile.json upload path/folderToUpload destinationFolderId --renameTo newFolderName"

## How to move folder

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@ class UploadCommand : BaseCommand() {
@CommandLine.Option(names = ["--renameTo"], description = ["Rename the file or folder in to that name."])
var renameTo: String = ""

@CommandLine.Option(names = ["--checksum"], description = ["Whether a sha-256 checksum file should also be uploaded."])
var uploadChecksum = false

@CommandLine.Parameters(paramLabel = "source", description = ["Source path to the file or folder to upload."])
lateinit var source: String

@CommandLine.Parameters(paramLabel = "destinationId", description = ["Id of the destination folder on Google drive where to upload to."])
lateinit var destinationId: String




override fun run() {
GDriveUploadTask(parentCommand.creds.readText(), source, destinationId, gdriveLogger, renameTo).execute()
GDriveUploadTask(parentCommand.creds.readText(), source, destinationId, gdriveLogger, renameTo, uploadChecksum).execute()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.google.api.services.drive.DriveScopes
import com.google.api.services.drive.model.File
import com.google.auth.http.HttpCredentialsAdapter
import com.google.auth.oauth2.GoogleCredentials
import java.security.MessageDigest

abstract class GDriveTask(private val logger: Logger, private val googleCredentials: String) {

Expand Down Expand Up @@ -45,16 +46,56 @@ abstract class GDriveTask(private val logger: Logger, private val googleCredenti
mimeType = FOLDER_MIMETYPE
parents = mutableListOf(parentFolderId)
}
// Check if the folder already exists
val query = "mimeType='$FOLDER_MIMETYPE' and name='$folderName' and '$parentFolderId' in parents and trashed=false";
val result = drive.files().list().setQ(query)
.setSupportsAllDrives(true)
.setIncludeItemsFromAllDrives(true)
.execute()
if(!result.getFiles().isEmpty()){
return result.getFiles().get(0)
}
folder = drive.files().create(folder).setFields("id").setSupportsAllDrives(true).execute()
return folder
}

protected fun uploadFile(drive: Drive, file: java.io.File, fileName: String, destinationFolder: File): File {
return drive.files().create(File().apply {
name = fileName
parents = mutableListOf(destinationFolder.id)
}, FileContent(null, file))
.setFields("id").setSupportsAllDrives(true).execute()
// Check if the file already exists
val query = "name='$fileName' and '${destinationFolder.id}' in parents and trashed=false";
val result = drive.files().list().setQ(query)
.setSupportsAllDrives(true)
.setIncludeItemsFromAllDrives(true)
.execute()
if(!result.getFiles().isEmpty()){ // Update it
val existingFile = result.getFiles().get(0)
val uploadedFile = drive.files().update(existingFile.id, File().apply {
name = fileName
}, FileContent(null, file))
.setFields("id,name,md5Checksum").setSupportsAllDrives(true).execute()
validateMd5Checksum(uploadedFile.md5Checksum, calculateMd5Checksum(file))
return uploadedFile
}else{ // Create it
val uploadedFile = drive.files().create(File().apply {
name = fileName
parents = mutableListOf(destinationFolder.id)
}, FileContent(null, file))
.setFields("id,name,md5Checksum").setSupportsAllDrives(true).execute()
validateMd5Checksum(uploadedFile.md5Checksum, calculateMd5Checksum(file))
return uploadedFile
}
}

fun validateMd5Checksum(uploadedFileChecksum : String, originalFileChecksum : String){
if(uploadedFileChecksum != originalFileChecksum){
throw RuntimeException("Uploaded file MD5 checksum does not match !");
}
}

fun calculateMd5Checksum(file: java.io.File): String {
val bytes = file.readBytes()
val digest = MessageDigest.getInstance("MD5")
val hashBytes = digest.digest(bytes)
return hashBytes.joinToString("") { "%02x".format(it) }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@ package org.bonitasoft.gdrive.core

import com.google.api.services.drive.Drive
import com.google.api.services.drive.model.File
import java.security.MessageDigest
import java.io.BufferedWriter
import java.io.FileWriter

class GDriveUploadTask(googleCredentials: String,
private val source: String,
private val destinationId: String,
private val logger: Logger,
private val renameTo: String) : GDriveTask(logger, googleCredentials) {
private val renameTo: String,
private val uploadChecksum: Boolean) : GDriveTask(logger, googleCredentials) {

override fun doExecute(drive: Drive) {

val destinationFolder = retrieveFolder(drive, destinationId)

logger.info("Will upload $source inside Drive folder ${destinationFolder.name} with id ${destinationFolder.id}")
copy(drive, java.io.File(source), destinationFolder, renameTo)
copy(drive, java.io.File(source), destinationFolder, renameTo, uploadChecksum)
logger.info("Uploaded all files to ${destinationFolder.id}")

return
}

private fun copy(drive: Drive, file: java.io.File, destinationFolder: File, renameTo: String = "") {
private fun copy(drive: Drive, file: java.io.File, destinationFolder: File, renameTo: String = "", uploadChecksum: Boolean) {
logger.debug("Processing ${file.absolutePath}")
val fileName = renameTo.trim().ifEmpty { file.name }
if (fileName != file.name) {
Expand All @@ -33,11 +37,36 @@ class GDriveUploadTask(googleCredentials: String,
val newFolder = createFolder(drive, fileName, destinationFolder.id)
logger.debug("Created folder $fileName with id ${newFolder.id}")
file.listFiles().forEach { child ->
copy(drive, child, newFolder)
copy(drive, child, newFolder, "", uploadChecksum)
}
} else {
val uploadFile = uploadFile(drive, file, fileName, destinationFolder)
logger.info("Uploaded file ${uploadFile.name} with id ${uploadFile.id}")
if(uploadChecksum){
val checksumFile = java.io.File.createTempFile(fileName, ".sha256")
writeTextToFile(calculateSHA256(file), checksumFile.absolutePath)
val uploadedCheckumFile = uploadFile(drive, checksumFile, fileName + ".sha256", destinationFolder)
logger.info("Uploaded file ${uploadedCheckumFile.name} with id ${uploadedCheckumFile.id}")
}
}
}

fun calculateSHA256(file: java.io.File): String {
val bytes = file.readBytes()
val digest = MessageDigest.getInstance("SHA-256")
val hashBytes = digest.digest(bytes)
return hashBytes.joinToString("") { "%02x".format(it) }
}

fun writeTextToFile(text: String, filePath: String) {
val file = java.io.File(filePath)

try {
BufferedWriter(FileWriter(file)).use { writer ->
writer.write(text)
}
} catch (e: Exception) {
logger.error("An error occurred while writing to the file: $e")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ constructor(
val googleCredentials: String,
val source: String,
val destinationId: String,
val renameTo: String
val renameTo: String,
val uploadChecksum : Boolean = false
) : Step() {
override fun start(context: StepContext) = GDriveUploadStepExecution(
googleCredentials,
source,
destinationId,
renameTo,
uploadChecksum,
context
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class GDriveUploadStepExecution(
private val source: String,
private val destinationId: String,
private val renameTo: String,
private val uploadChecksum : Boolean,
context: StepContext) : SynchronousNonBlockingStepExecution<Void>(context) {

override fun run(): Void? {
Expand All @@ -27,7 +28,7 @@ class GDriveUploadStepExecution(

val workspace = context.get(FilePath::class.java)!!
logger.println("Starting the upload of $source to the destination $destinationId, all logs will be displayed once the upload is completed")
val logs = workspace.child(source).act(UploadFile(googleCredentials, destinationId, renameTo))
val logs = workspace.child(source).act(UploadFile(googleCredentials, destinationId, renameTo, uploadChecksum))
logs.forEach { logger.println(it) }
return null
} catch (e: Throwable) {
Expand All @@ -39,7 +40,7 @@ class GDriveUploadStepExecution(

}

class UploadFile(val googleCredentials: String, val destinationId: String, val renameTo: String) : FileCallable<List<String>>, Serializable {
class UploadFile(val googleCredentials: String, val destinationId: String, val renameTo: String, val uploadChecksum: Boolean) : FileCallable<List<String>>, Serializable {

override fun checkRoles(p0: RoleChecker?) = Unit
override fun invoke(file: File?, p1: VirtualChannel?): List<String> {
Expand All @@ -64,7 +65,7 @@ class UploadFile(val googleCredentials: String, val destinationId: String, val r
logs.add("ERROR: $message")
}
}
GDriveUploadTask(googleCredentials, file.absolutePath, destinationId, gdriveLogger, renameTo).execute()
GDriveUploadTask(googleCredentials, file.absolutePath, destinationId, gdriveLogger, renameTo, uploadChecksum).execute()
return logs
}
}

0 comments on commit 4a0d44a

Please sign in to comment.