Skip to content

Commit

Permalink
Merge pull request #148 from SamSchott/develop
Browse files Browse the repository at this point in the history
bump to v1.0.3
  • Loading branch information
SamSchott authored May 21, 2020
2 parents 30a2e42 + 928834b commit e5ecb6c
Show file tree
Hide file tree
Showing 37 changed files with 1,463 additions and 1,060 deletions.
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
## v1.0.3.dev

#### Changed:

- Both "-h" and "--help" can now be used to print help output for a command.
- Show both the daemon and GUI version in the GUI settings window.
- The command line tool bundled with the macOS app now provides proper help output.
- Significantly reduced CPU usage of the GUI on macOS.
- The macOS app now uses a hardened runtime and is properly signed and notarized.

#### Fixed:

- Fixes an issue which could lead to the local Dropbox folder being moved before syncing
has been paused.
- Fixes an issue where download errors would show a rev number instead of the Dropbox
path.
- Fixes a race condition when two processes try to start a sync daemon at the same time.
- Fixes an issue in the macOS GUI where updating the displayed sync issues could fail.
- Fixes truncated text in the macOS setup dialog.
- Fixes an issue on fresh macOS installs where creating autostart entries could fail if
/Library/LaunchAgents does not yet exist.
- Fixes an issue in the macOS app bundle where installing the command line could tool
would fail if /usr/local/bin is owned by root (as is default on a fresh install). Now,
the user is asked for permission instead.

#### Dependencies:

- Removed `lockfile` dependency.
- Added `fasteners` dependency.

## v1.0.2

This release fixes bugs in the command line interface.
Expand Down
7 changes: 2 additions & 5 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@

#### Short term:

* Switch from implicit grant to PKCE OAuth flow as soon as Dropbox supports it (DONE).
* Snap package once core20 is released and kde-neon works on core20.
* CLI autocomplete for paths once there is better support from upstream `click`.
* Update macOS app bundle to Python 3.8 and Qt 5.14.
* Update macOS app bundle to Python 3.8.

#### Long term:

* deb and rpm packages: either with Pyinstaller executable or as Python package.
* GUI support for multiple Dropbox accounts.
* Option to install command line scripts from macOS app bundle (DONE).
* Work with upstream `toga` to fix remaining issues for native macOS GUI,
notably memory leak in `rubicon.objc` (DONE).
* Consider using sqlite for index and state.
1 change: 1 addition & 0 deletions docs/api/sync.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ Sync module

.. automodule:: sync
:members:
:private-members:
:show-inheritance:
7 changes: 0 additions & 7 deletions docs/api/utils/backend.rst

This file was deleted.

2 changes: 0 additions & 2 deletions docs/api/utils/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ maestral.utils

utils.appdirs <appdirs>
utils.autostart <autostart>
utils.backend <backend>
utils.housekeeping <housekeeping>
utils.notify <notify>
utils.oauth_implicit <oauth_implicit>
utils.path <path>
utils.serializer <serializer>
utils.updates <updates>
7 changes: 0 additions & 7 deletions docs/api/utils/oauth_implicit.rst

This file was deleted.

68 changes: 68 additions & 0 deletions docs/config_files.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@

Config files
============

The config files are located at ``$XDG_CONFIG_HOME/maestral`` on Linux (typically
``~/.config/maestral``) and ``~/Library/Application Support/maestral`` on macOS. Each
configuration will get its own INI file with the settings documented below.

Config values in the sections ``main`` and ``account`` should not be edited manually but
rather through the corresponding CLI commands or GUI options. This is because changes of
these settings require Maestral to perform accompanying actions, e.g., download items
which have been removed from the excluded list or move the local Dropbox directory.
Those will not be performed if the user edits the options manually.

Changes to the other sections may be performed manually but will only take effect once
Maestral is restarted. Maestral will overwrite the entire config file if any change is
made to one of the options through the ``maestral.config`` module.

.. code-block:: ini
[main]
# The current Dropbox directory
path = /Users/samschott/Dropbox (Maestral)
# Default directory name for the config
default_dir_name = Dropbox (Maestral)
# List of excluded files and folders
excluded_items = ['/test_folder', '/sub/folder']
# Config file version (not the Maestral version!)
version = 12.0.0
[account]
# Unique Dropbox account ID. The account's email
# address may change and is therefore not stored here.
account_id = dbid:AABP7CC5bpYd8cGHqIColDFrMoc9SdhACA4
[app]
# Level for desktop notifications:
# 15 = FILECHAANGE
# 30 = SYNCISSUE
# 40 = ERROR
# 100 = NONE
notification_level = 15
# Level for log messages:
# 10 = DEBUG
# 20 = INFO
# 30 = WARNING
# 40 = ERR0R
log_level = 20
# Interval in sec to check for updates
update_notification_interval = 604800
# Enable or disable automatic error reports
analytics = False
[sync]
# Interval in sec to perform a full reindexing
reindex_interval = 604800
# Maximum CPU usage per core
max_cpu_percent = 20.0
6 changes: 3 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ refer to the `wiki <https://github.com/SamSchott/maestral-dropbox/wiki>`_.
The following APIs should remain stable for frontends such as the GUI or CLI:

* maestral.main.Maestral
* maestral.constants
* maestral.daemon
* maestral.constants
* maestral.errors
* maestral.utils.appdirs
* maestral.utils.autostart

.. toctree::
:caption: Table of Contents
:maxdepth: 2

config_files
state_files
api/index

.. toctree::
Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ atomicwrites
bugsnag
click
dropbox
fasteners
importlib_metadata
keyring
keyrings.alt
lockfile
packaging
pathspec
Pyro5
Expand Down
65 changes: 65 additions & 0 deletions docs/state_files.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

State files
===========

Maestral saves its persistent state in two files: "{config_name}.index" for the file
index and "{config_name}.state" for anything else. Both files are located at
$XDG_DATA_DIR/maestral on Linux (typically ~/.local/share/maestral) and
~/Library/Application Support/maestral on macOS. Each configuration will get its own
state file.


Index file
**********

The index file contains all the tracked files and folders with their lower-case path
relative to the Dropbox folder and their "rev". Each line contains a single entry, written
as a dictionary ``{path: rev}`` in json format, for example:

.. code-block:: python
{"/test folder/subfolder/file.txt": "015a4ae1f15853400000001695a6c40"}
If there are multiple entries (lines) which refer to the same path, the last entry
overwrites any previous entries. This allows rapidly updating the rev for a file or folder
by appending a new line to the index file without needing to write an entire file.

An entry with ``rev == None`` means that any previous entries for this path and its
children should be discarded.

After a sync cycle has completed, the file is cleaned up and all duplicate or empty
entries are removed.


State file
**********

The state file has the following sections:

.. code-block:: ini
[account]
email = foo@bar.com
display_name = Foo Bar
abbreviated_name = FB
type = business
usage = 39.2% of 1312.8TB used
usage_type = team
[app]
update_notification_last = 0.0
latest_release = 1.0.3
[sync]
cursor = ...
lastsync = 1589979736.623609
last_reindex = 1589577566.8533309
download_errors = []
pending_downloads = []
recent_changes = []
[main]
version = 12.0.0
Notably, account info which can be changed by the user such as the email address is saved
in the state file while only the fixed Dropbox ID is saved in the config file.
2 changes: 1 addition & 1 deletion maestral/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"""

__version__ = '1.0.2'
__version__ = '1.0.3'
__author__ = 'Sam Schott'
__url__ = 'https://github.com/SamSchott/maestral'
50 changes: 14 additions & 36 deletions maestral/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import Pyro5.errors

# local imports
from maestral.daemon import freeze_support
from maestral.config import MaestralConfig, MaestralState, list_configs
from maestral.utils.housekeeping import remove_configuration

Expand Down Expand Up @@ -362,33 +363,13 @@ def _run_daemon(ctx, param, value):
)


hidden_config_option = click.option(
'-c', '--config-name',
default='maestral',
is_eager=True,
expose_value=False,
help='For internal use only.',
hidden=True,
)
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])


frozen_daemon_option = click.option(
'--frozen-daemon',
is_flag=True,
default=False,
is_eager=True,
expose_value=False,
callback=_run_daemon,
hidden=True,
help='For internal use only.'
)


@click.group(cls=SpecialHelpOrder)
@frozen_daemon_option
@hidden_config_option
@click.group(cls=SpecialHelpOrder, context_settings=CONTEXT_SETTINGS)
def main():
"""Maestral Dropbox Client for Linux and macOS."""
"""Maestral Dropbox client for Linux and macOS."""
freeze_support()
check_for_updates()


Expand Down Expand Up @@ -445,16 +426,10 @@ def gui(config_name):
def start(config_name: str, foreground: bool, verbose: bool):
"""Starts the Maestral daemon."""

from maestral.daemon import get_maestral_pid, get_maestral_proxy
from maestral.daemon import get_maestral_proxy
from maestral.daemon import (start_maestral_daemon_thread, threads,
start_maestral_daemon_process, Start)

# do nothing if already running
if get_maestral_pid(config_name):
click.echo('Maestral daemon is already running.')
return

# start daemon
click.echo('Starting Maestral...', nl=False)

if foreground:
Expand All @@ -464,6 +439,9 @@ def start(config_name: str, foreground: bool, verbose: bool):

if res == Start.Ok:
click.echo('\rStarting Maestral... ' + OK)
elif res == Start.AlreadyRunning:
click.echo('\rStarting Maestral... Already running.')
return
else:
click.echo('\rStarting Maestral... ' + FAILED)
click.echo('Please check logs for more information.')
Expand Down Expand Up @@ -841,14 +819,14 @@ def rebuild_index(config_name: str):
@main.command(help_priority=16)
def configs():
"""Lists all configured Dropbox accounts."""
from maestral.daemon import get_maestral_pid
from maestral.daemon import is_running

# clean up stale configs
config_names = list_configs()

for name in config_names:
dbid = MaestralConfig(name).get('account', 'account_id')
if dbid == '' and not get_maestral_pid(name):
if dbid == '' and not is_running(name):
remove_configuration(name)

# display remaining configs
Expand All @@ -868,8 +846,8 @@ def analytics(config_name: str, yes: bool, no: bool):
"""
Enables or disables sharing error reports.
Sharing is disabled by default. If enbled, error reports are shared with bugsnag and
no personal infortmation will typically be collected. Shared tracebacks may however
Sharing is disabled by default. If enabled, error reports are shared with bugsnag and
no personal information will typically be collected. Shared tracebacks may however
include file names, depending on the error.
"""

Expand Down Expand Up @@ -1132,4 +1110,4 @@ def notify_snooze(config_name: str, minutes: int):
click.echo(f'Notifications snoozed for {minutes} min. '
'Set snooze to 0 to reset.')
else:
click.echo(f'Notifications enabled.')
click.echo('Notifications enabled.')
Loading

0 comments on commit e5ecb6c

Please sign in to comment.