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

Add storage engine for Microsoft OneDrive #1910

Open
wants to merge 1 commit into
base: master
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Added support for PrusaSlicer (via @visika)
- Added support for Logseq (via @visika)
- Added support for SwitchHosts (via @zxjlm)
- Added support for Microsoft OneDrive as a new storage engine (via @burck1)

## Mackup 0.8.36

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ in it stay put, so that any other computer also running Mackup is unaffected.
- [Google Drive](https://drive.google.com/)
- [Copy](https://www.copy.com/)
- [iCloud](http://www.apple.com/icloud/)
- [Microsoft OneDrive](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage/)
- Anything able to sync a folder (e.g. [Git](http://git-scm.com/))

See the [README](doc/README.md) file in the doc directory for more info.
Expand Down
18 changes: 11 additions & 7 deletions doc/.mackup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@
# Sample Mackup configuration file
#

# You can specify the storage type Mackup will use to store your configuration
# files.
# For now you have 3 options: "dropbox", "google_drive" and "file_system".
# You can specify the storage type Mackup will use to store your configuration files.
# Options include: dropbox, google_drive, icloud, microsoft_onedrive, copy, file_system
# If none is specified, Mackup will try to use the default: "dropbox".
# With the "dropbox" storage engine, Mackup will automatically figure out your
# Dropbox folder.
[storage]
engine = dropbox

# If you choose the "google_drive" storage engine instead, Mackup will figure
# out where your Google Drive is and store your configuration files in it.
# Similarily, if you choose the "google_drive", "icloud", "microsoft_onedrive" or "copy"
# storage engine, Mackup will figure out your path and store your configuration files in it.

# [storage]
# engine = google_drive

# If you choose the "copy" storage engine, Mackup will figure
# out where your Copy folder is and store your configuration files in it.
# [storage]
# engine = icloud

# [storage]
# engine = microsoft_onedrive

# [storage]
# engine = copy

Expand Down
16 changes: 14 additions & 2 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ vi ~/.mackup.cfg
## Storage

You can specify the storage type Mackup will use to store your configuration
files.
files. Options include:

For now, you have 4 options: `dropbox`, `google_drive`, `icloud`, `copy` and `file_system`.
- `dropbox`
- `google_drive`
- `icloud`
- `microsoft_onedrive`
- `copy`
- `file_system`

If none is specified, Mackup will try to use the default: `dropbox`.
With the `dropbox` storage engine, Mackup will automatically figure out your
Expand Down Expand Up @@ -44,6 +49,13 @@ engine = google_drive
engine = icloud
```

### Microsoft OneDrive

```ini
[storage]
engine = microsoft_onedrive
```

### Copy

If you choose the `copy` storage engine, Mackup will figure out
Expand Down
2 changes: 0 additions & 2 deletions mackup/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ def backup(self):
and (os.path.isfile(mackup_filepath) or os.path.isdir(mackup_filepath))
and os.path.samefile(home_filepath, mackup_filepath)
):

if self.verbose:
print(
"Backing up\n {}\n to\n {} ...".format(
Expand All @@ -87,7 +86,6 @@ def backup(self):

# Check if we already have a backup
if os.path.exists(mackup_filepath):

# Name it right
if os.path.isfile(mackup_filepath):
file_type = "file"
Expand Down
7 changes: 6 additions & 1 deletion mackup/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ENGINE_COPY,
ENGINE_ICLOUD,
ENGINE_FS,
ENGINE_MSONEDRIVE,
)

from .utils import (
Expand All @@ -20,6 +21,7 @@
get_copy_folder_location,
get_google_drive_folder_location,
get_icloud_folder_location,
get_microsoft_onedrive_folder_location,
)

try:
Expand Down Expand Up @@ -68,7 +70,7 @@ def engine(self):
"""
The engine used by the storage.

ENGINE_DROPBOX, ENGINE_GDRIVE, ENGINE_COPY, ENGINE_ICLOUD or ENGINE_FS.
ENGINE_DROPBOX, ENGINE_GDRIVE, ENGINE_COPY, ENGINE_ICLOUD, ENGINE_MSONEDRIVE, or ENGINE_FS.

Returns:
str
Expand Down Expand Up @@ -194,6 +196,7 @@ def _parse_engine(self):
ENGINE_COPY,
ENGINE_ICLOUD,
ENGINE_FS,
ENGINE_MSONEDRIVE,
]:
raise ConfigError("Unknown storage engine: {}".format(engine))

Expand All @@ -214,6 +217,8 @@ def _parse_path(self):
path = get_copy_folder_location()
elif self.engine == ENGINE_ICLOUD:
path = get_icloud_folder_location()
elif self.engine == ENGINE_MSONEDRIVE:
path = get_microsoft_onedrive_folder_location()
elif self.engine == ENGINE_FS:
if self._parser.has_option("storage", "path"):
cfg_path = self._parser.get("storage", "path")
Expand Down
1 change: 1 addition & 0 deletions mackup/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
ENGINE_FS = "file_system"
ENGINE_GDRIVE = "google_drive"
ENGINE_ICLOUD = "icloud"
ENGINE_MSONEDRIVE = "microsoft_onedrive"

DOCUMENTATION_URL = "https://github.com/lra/mackup/blob/master/doc/README.md"

Expand Down
1 change: 0 additions & 1 deletion mackup/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ def printAppHeader(app_name):
"Are you sure?"
)
):

# Uninstall the apps except Mackup, which we'll uninstall last, to
# keep the settings as long as possible
app_names = mckp.get_apps_to_backup()
Expand Down
33 changes: 33 additions & 0 deletions mackup/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,39 @@ def get_icloud_folder_location():
return str(icloud_home)


def get_microsoft_onedrive_folder_location():
"""
Try to locate the Microsoft OneDrive folder.

Returns:
(str) Full path to the current Microsoft OneDrive folder
"""
# the OneDrive sync path should always be found at ~/Library/CloudStorage/OneDrive-*/
onedrive_paths = get_cloud_storage_paths("OneDrive-")
if not onedrive_paths:
error(
constants.ERROR_UNABLE_TO_FIND_STORAGE.format(
provider="Microsoft OneDrive install"
)
)
# if there are multiple OneDrive paths, choose the first
return sorted(onedrive_paths, key=lambda p: p.name)[0].path


def get_cloud_storage_paths(prefix=None):
# The Cloud Storage path is found at ~/Library/CloudStorage/. This is the standard path used for all
# storage providers as of macOS 10.15+. ref: https://developer.apple.com/documentation/fileprovider.
cloud_storage_root_path = os.path.join(os.environ["HOME"], "Library/CloudStorage")
if not os.path.exists(cloud_storage_root_path):
return []
cloud_storage_paths = (p for p in os.scandir(cloud_storage_root_path) if p.is_dir())
if prefix:
cloud_storage_paths = (
p for p in cloud_storage_paths if p.name.lower().startswith(prefix.lower())
)
return cloud_storage_paths


def is_process_running(process_name):
"""
Check if a process with the given name is running.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
author_email="[email protected]",
url="https://github.com/lra/mackup",
description="Keep your application settings in sync (macOS/Linux)",
keywords="configuration config dotfiles sync backup dropbox gdrive box",
keywords="configuration config dotfiles sync backup dropbox gdrive icloud onedrive",
license="GPLv3",
packages=["mackup"],
install_requires=["docopt", "six"],
Expand Down
17 changes: 17 additions & 0 deletions tests/config_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
ENGINE_COPY,
ENGINE_ICLOUD,
ENGINE_FS,
ENGINE_MSONEDRIVE,
)
from mackup.config import Config, ConfigError

Expand Down Expand Up @@ -168,6 +169,22 @@ def test_config_engine_icloud(self):
assert cfg.apps_to_ignore == set(["subversion", "sequel-pro", "sabnzbd"])
assert cfg.apps_to_sync == set(["sublime-text-3", "x11", "sabnzbd"])

def test_config_engine_microsoft_onedrive(self):
cfg = Config("mackup-engine-microsoft_onedrive.cfg")

assert isinstance(cfg.engine, str)
assert cfg.engine == ENGINE_MSONEDRIVE

assert isinstance(cfg.path, str)
assert cfg.path == os.path.join(
os.environ["HOME"], "Library/CloudStorage/OneDrive-Personal"
)

assert isinstance(cfg.fullpath, str)
assert cfg.fullpath == os.path.join(
os.environ["HOME"], "Library/CloudStorage/OneDrive-Personal/Mackup"
)

def test_config_engine_filesystem_no_path(self):
with self.assertRaises(ConfigError):
Config("mackup-engine-file_system-no_path.cfg")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Blank file for git sync
2 changes: 2 additions & 0 deletions tests/fixtures/mackup-engine-microsoft_onedrive.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[storage]
engine = microsoft_onedrive