Skip to content

Commit

Permalink
Merge branch 'onedrive-v2.5.0-alpha-2' into pr/2519
Browse files Browse the repository at this point in the history
  • Loading branch information
abraunegg committed Oct 19, 2023
2 parents 7ece476 + 380e316 commit 8f74f40
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 32 deletions.
24 changes: 16 additions & 8 deletions docs/application-config-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -859,9 +859,11 @@ _**Usage Example:**_ `onedrive --confdir '~/.config/onedrive-business/'`
_**Additional Usage Notes:**_ If using this option, it must be specified each and every time the application is used. If this is ommited, the application default configuration directory will be used.

### CLI Option: --create-directory
_**Description:**_
_**Description:**_ This CLI option allows the user to create the specified directory path on Microsoft OneDrive without performing a sync.

_**Usage Example:**_
_**Usage Example:**_ `onedrive --create-directory 'path/of/new/folder/structure/to/create/'`

_**Additional Usage Notes:**_ The specified path to create is relative to your configured 'sync_dir'.

### CLI Option: --create-share-link
_**Description:**_ This CLI option enables the creation of a shareable file link that can be provided to users to access the file that is stored on Microsoft OneDrive. By default, the permissions for the file will be 'read-only'.
Expand All @@ -871,9 +873,11 @@ _**Usage Example:**_ `onedrive --create-share-link 'relative/path/to/your/file.t
_**Additional Usage Notes:**_ If writable access to the file is required, you must add `--with-editing-perms` to your command. See below for details.

### CLI Option: --destination-directory
_**Description:**_
_**Description:**_ This CLI option specifies the 'destination' portion of moving a file or folder online, without performing a sync operation.

_**Usage Example:**_ `onedrive --source-directory 'path/as/source/' --destination-directory 'path/as/destination'`

_**Usage Example:**_
_**Additional Usage Notes:**_ All specified paths are relative to your configured 'sync_dir'.

### CLI Option: --display-config
_**Description:**_ This CLI option will display the effective application configuration
Expand Down Expand Up @@ -952,9 +956,11 @@ _**Description:**_ This CLI option controls the ability to re-authenticate your
_**Usage Example:**_ `onedrive --reauth`

### CLI Option: --remove-directory
_**Description:**_
_**Description:**_ This CLI option allows the user to remove the specified directory path on Microsoft OneDrive without performing a sync.

_**Usage Example:**_
_**Usage Example:**_ `onedrive --remove-directory 'path/of/new/folder/structure/to/remove/'`

_**Additional Usage Notes:**_ The specified path to remove is relative to your configured 'sync_dir'.

### CLI Option: --single-directory
_**Description:**_ This CLI option controls the applications ability to sync a specific single directory.
Expand All @@ -964,9 +970,11 @@ _**Usage Example:**_ `onedrive --sync --single-directory 'Data'`
_**Additional Usage Notes:**_ The path specified is relative to your configured 'sync_dir' path. If the physical local path 'Folder' to sync is `~/OneDrive/Data/Folder` then the command would be `--single-directory 'Data/Folder'`.

### CLI Option: --source-directory
_**Description:**_
_**Description:**_ This CLI option specifies the 'source' portion of moving a file or folder online, without performing a sync operation.

_**Usage Example:**_ `onedrive --source-directory 'path/as/source/' --destination-directory 'path/as/destination'`

_**Usage Example:**_
_**Additional Usage Notes:**_ All specified paths are relative to your configured 'sync_dir'.

### CLI Option: --sync | -s
_**Description:**_ This CLI option controls the 'Standalone Mode' operational aspect of the client. When this option is used, the client will perform a one-time sync of data between Microsoft OneDrive and your local system.
Expand Down
54 changes: 51 additions & 3 deletions src/config.d
Original file line number Diff line number Diff line change
Expand Up @@ -1986,14 +1986,14 @@ class ApplicationConfig {
operationalConflictDetected = true;
}

// --get-O365-drive-id cannot be used with --resync and/or --resync-auth
// --get-sharepoint-drive-id cannot be used with --resync and/or --resync-auth
if ((!getValueString("sharepoint_library_name").empty) && ((getValueBool("resync")) || (getValueBool("resync_auth")))) {
log.error("ERROR: --get-O365-drive-id cannot be used with --resync or --resync-auth.");
log.error("ERROR: --get-sharepoint-drive-id cannot be used with --resync or --resync-auth.");
operationalConflictDetected = true;
}

// --monitor and --display-sync-status cannot be used together
if ( (getValueBool("monitor")) && (getValueBool("display_sync_status"))) {
if ((getValueBool("monitor")) && (getValueBool("display_sync_status"))) {
log.error("ERROR: --monitor and --display-sync-status cannot be used together.");
operationalConflictDetected = true;
}
Expand Down Expand Up @@ -2036,6 +2036,54 @@ class ApplicationConfig {
operationalConflictDetected = true;
}

// --monitor and --create-directory cannot be used together
if ((getValueBool("monitor")) && (!getValueString("create_directory").empty)) {
log.error("ERROR: --monitor and --create-directory cannot be used together.");
operationalConflictDetected = true;
}

// --sync and --create-directory cannot be used together
if ((getValueBool("synchronize")) && (!getValueString("create_directory").empty)) {
log.error("ERROR: --sync and --create-directory cannot be used together.");
operationalConflictDetected = true;
}

// --monitor and --remove-directory cannot be used together
if ((getValueBool("monitor")) && (!getValueString("remove_directory").empty)) {
log.error("ERROR: --monitor and --remove-directory cannot be used together.");
operationalConflictDetected = true;
}

// --sync and --remove-directory cannot be used together
if ((getValueBool("synchronize")) && (!getValueString("remove_directory").empty)) {
log.error("ERROR: --sync and --remove-directory cannot be used together.");
operationalConflictDetected = true;
}

// --monitor and --source-directory cannot be used together
if ((getValueBool("monitor")) && (!getValueString("source_directory").empty)) {
log.error("ERROR: --monitor and --source-directory cannot be used together.");
operationalConflictDetected = true;
}

// --sync and --source-directory cannot be used together
if ((getValueBool("synchronize")) && (!getValueString("source_directory").empty)) {
log.error("ERROR: --sync and --source-directory cannot be used together.");
operationalConflictDetected = true;
}

// --monitor and --destination-directory cannot be used together
if ((getValueBool("monitor")) && (!getValueString("destination_directory").empty)) {
log.error("ERROR: --monitor and --destination-directory cannot be used together.");
operationalConflictDetected = true;
}

// --sync and --destination-directory cannot be used together
if ((getValueBool("synchronize")) && (!getValueString("destination_directory").empty)) {
log.error("ERROR: --sync and --destination-directory cannot be used together.");
operationalConflictDetected = true;
}

// Return bool value indicating if we have an operational conflict
return operationalConflictDetected;
}
Expand Down
35 changes: 33 additions & 2 deletions src/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ int main(string[] cliArgs) {
// - Are we getting the URL for a file online
// - Are we listing who modified a file last online
// - Are we createing a shareable link for an existing file on OneDrive?
// - Are we just creating a directory online, without any sync being performed?
// - Are we just deleting a directory online, without any sync being performed?
// - Are we renaming or moving a directory?

// --get-sharepoint-drive-id - Get the SharePoint Library drive_id
if (appConfig.getValueString("sharepoint_library_name") != "") {
Expand Down Expand Up @@ -458,6 +461,34 @@ int main(string[] cliArgs) {
return EXIT_SUCCESS;
}

// --create-directory - Are we just creating a directory online, without any sync being performed?
if ((appConfig.getValueString("create_directory") != "")) {
// Handle the remote path creation and updating of the local database without performing a sync
syncEngineInstance.createDirectoryOnline(appConfig.getValueString("create_directory"));
// Exit application
// Use exit scopes to shutdown API
return EXIT_SUCCESS;
}

// --remove-directory - Are we just deleting a directory online, without any sync being performed?
if ((appConfig.getValueString("remove_directory") != "")) {
// Handle the remote path deletion without performing a sync
syncEngineInstance.deleteByPath(appConfig.getValueString("remove_directory"));
// Exit application
// Use exit scopes to shutdown API
return EXIT_SUCCESS;
}

// Are we renaming or moving a directory?
// onedrive --source-directory 'path/as/source/' --destination-directory 'path/as/destination'
if ((appConfig.getValueString("source_directory") != "") && (appConfig.getValueString("destination_directory") != "")) {
// We are renaming or moving a directory
syncEngineInstance.uploadMoveItem(appConfig.getValueString("source_directory"), appConfig.getValueString("destination_directory"));
// Exit application
// Use exit scopes to shutdown API
return EXIT_SUCCESS;
}

// If we get to this point, we have not performed a 'no-sync' task ..
log.error("\nYour command line input is missing either the '--sync' or '--monitor' switches. Please include one (but not both) of these switches in your command line, or refer to 'onedrive --help' for additional guidance.\n");
log.error("It is important to note that you must include one of these two arguments in your command line for the application to perform a synchronisation with Microsoft OneDrive\n");
Expand Down Expand Up @@ -634,15 +665,15 @@ int main(string[] cliArgs) {

// Delegated function for when inotify detects a delete event
filesystemMonitor.onDelete = delegate(string path) {
log.log("Received inotify delete event from operating system .. attempting item deletion as requested");
log.vlog("[M] Local item deleted: ", path);
try {
log.log("The operating system sent a deletion notification. Trying to delete the item as requested");
syncEngineInstance.deleteByPath(path);
} catch (CurlException e) {
log.vlog("Offline, cannot delete item!");
} catch(SyncException e) {
if (e.msg == "The item to delete is not in the local database") {
log.vlog("Item cannot be deleted from OneDrive because it was not found in the local database");
log.vlog("Item cannot be deleted from Microsoft OneDrive because it was not found in the local database");
} else {
log.logAndNotify("Cannot delete remote item: ", e.msg);
}
Expand Down
66 changes: 47 additions & 19 deletions src/sync.d
Original file line number Diff line number Diff line change
Expand Up @@ -704,15 +704,15 @@ class SyncEngine {
currentDeltaLink = null;
}

// Dynamic output for a non-verbose run so that the user knows something is happening
if (log.verbose == 0) {
// Dynamic output for non-verbose and verbose run so that the user knows something is being retreived from the OneDrive API
if (log.verbose <= 1) {
if (!appConfig.surpressLoggingOutput) {
log.fileOnly("Fetching items from the OneDrive API for Drive ID: ", driveIdToQuery);
// Use the dots to show the application is 'doing something'
write("Fetching items from the OneDrive API for Drive ID: ", driveIdToQuery, " .");
}
} else {
log.vlog("Fetching /delta response from the OneDrive API for Drive ID: ", driveIdToQuery);
log.vdebug("Fetching /delta response from the OneDrive API for Drive ID: ", driveIdToQuery);
}

// Create a new API Instance for querying /delta and initialise it
Expand All @@ -738,7 +738,7 @@ class SyncEngine {
ulong nrChanges = count(deltaChanges["value"].array);
int changeCount = 0;

if (log.verbose == 0) {
if (log.verbose <= 1) {
// Dynamic output for a non-verbose run so that the user knows something is happening
if (!appConfig.surpressLoggingOutput) {
write(".");
Expand Down Expand Up @@ -791,7 +791,7 @@ class SyncEngine {
object.destroy(getDeltaQueryOneDriveApiInstance);

// Log that we have finished querying the /delta API
if (log.verbose == 0) {
if (log.verbose <= 1) {
if (!appConfig.surpressLoggingOutput) {
write("\n");
}
Expand Down Expand Up @@ -2367,7 +2367,7 @@ class SyncEngine {
// Display accountType, defaultDriveId, defaultRootId & remainingFreeSpace for verbose logging purposes
//log.vlog("Application version: ", strip(import("version")));

string tempVersion = "v2.5.0-alpha-2" ~ " GitHub version: " ~ strip(import("version"));
string tempVersion = "v2.5.0-alpha-3" ~ " GitHub version: " ~ strip(import("version"));
log.vlog("Application version: ", tempVersion);

log.vlog("Account Type: ", appConfig.accountType);
Expand Down Expand Up @@ -2947,6 +2947,12 @@ class SyncEngine {
// Return a true|false response

bool clientSideRuleExcludesPath = false;

// does the path exist?
if (!exists(localFilePath)) {
// path does not exist - we cant review any client side rules on something that does not exist locally
return clientSideRuleExcludesPath;
}

// - check_nosync
if (!clientSideRuleExcludesPath) {
Expand Down Expand Up @@ -4139,21 +4145,22 @@ class SyncEngine {

// Step 2: Query for the path online
if (!pathFoundInDB) {

// path not found in database
try {
log.vdebug("Attempting to query OneDrive Online for this parent path as path not found in local database: ", parentPath);
onlinePathData = createDirectoryOnlineOneDriveApiInstance.getPathDetails(parentPath);
// Save item to the database
saveItem(onlinePathData);
parentItem = makeItem(onlinePathData);
} catch (OneDriveException exception) {

if (exception.httpStatusCode == 404) {
// Parent does not exist ... need to create parent
log.vdebug("Parent path does not exist online: ", parentPath);
createDirectoryOnline(parentPath);
// no return here as we need to continue, but need to re-query the OneDrive API to get the right parental details now that they exist
onlinePathData = createDirectoryOnlineOneDriveApiInstance.getPathDetails(parentPath);
parentItem = makeItem(onlinePathData);
} else {

string thisFunctionName = getFunctionName!({});
// HTTP request returned status code 408,429,503,504
if ((exception.httpStatusCode == 408) || (exception.httpStatusCode == 429) || (exception.httpStatusCode == 503) || (exception.httpStatusCode == 504)) {
Expand Down Expand Up @@ -4186,12 +4193,10 @@ class SyncEngine {
}
}
}

} else {
// parent path found in database ... use those details ...
parentItem = databaseItem;
}

}

// Make sure the full path does not exist online, this should generate a 404 response, to which then the folder will be created online
Expand Down Expand Up @@ -4293,6 +4298,7 @@ class SyncEngine {
}
} else {
// Simulate a successful 'directory create' & save it to the dryRun database copy
log.log("Successfully created the remote directory ", thisNewPathToCreate, " on OneDrive");
// The simulated response has to pass 'makeItem' as part of saveItem
auto fakeResponse = createFakeResponse(thisNewPathToCreate);
// Save item to the database
Expand Down Expand Up @@ -4341,7 +4347,7 @@ class SyncEngine {

// If we get to this point - onlinePathData = createDirectoryOnlineOneDriveApiInstance.getPathDetailsByDriveId(parentItem.driveId, thisNewPathToCreate) generated a 'valid' response ....
// This means that the folder potentially exists online .. which is odd .. as it should not have existed
if (onlinePathData.type() == JSONType.object){
if (onlinePathData.type() == JSONType.object) {
// A valid object was responded with
if (onlinePathData["name"].str == baseName(thisNewPathToCreate)) {
// OneDrive 'name' matches local path name
Expand Down Expand Up @@ -5179,7 +5185,6 @@ class SyncEngine {
// If the item is a remote item, delete the reference in the local database
itemDB.deleteById(itemToDelete.remoteDriveId, itemToDelete.remoteId);
}

} else {
// log that this is a dry-run activity
log.log("dry run - no delete activity");
Expand Down Expand Up @@ -6227,8 +6232,8 @@ class SyncEngine {
}

// Delete an item by it's path
// This function is only used in --monitor mode
void deleteByPath(const(string) path) {
// This function is only used in --monitor mode and --remove-directory directive
void deleteByPath(string path) {

// function variables
Item dbItem;
Expand All @@ -6242,10 +6247,22 @@ class SyncEngine {
break;
}
}

// Was the item found in the database?
if (!itemInDB) {
throw new SyncException("The item to delete is not in the local database");
// path to delete is not in the local database ..
// was this a --remove-directory attempt?
if (!appConfig.getValueBool("monitor")) {
// --remove-directory deletion attempt
log.error("The item to delete is not in the local database - unable to delete online");
return;
} else {
// normal use .. --monitor being used
throw new SyncException("The item to delete is not in the local database");
}
}

// This needs to be enforced as we have to know the parent id of the object being deleted
if (dbItem.parentId == null) {
// the item is a remote folder, need to do the operation on the parent
enforce(itemDB.selectByPathWithoutRemote(path, appConfig.defaultDriveId, dbItem));
Expand Down Expand Up @@ -6346,12 +6363,23 @@ class SyncEngine {
}
} else {
if (!exists(newPath)) {
log.vlog("uploadMoveItem target has disappeared: ", newPath);
return;
// is this --monitor use?
if (appConfig.getValueBool("monitor")) {
log.vlog("uploadMoveItem target has disappeared: ", newPath);
return;
}
}

// Configure the modification JSON item
SysTime mtime = timeLastModified(newPath).toUTC();
SysTime mtime;
if (appConfig.getValueBool("monitor")) {
// Use the newPath modified timestamp
mtime = timeLastModified(newPath).toUTC();
} else {
// Use the current system time
mtime = Clock.currTime().toUTC();
}

JSONValue data = [
"name": JSONValue(baseName(newPath)),
"parentReference": JSONValue([
Expand Down

0 comments on commit 8f74f40

Please sign in to comment.