diff --git a/dvc/command/base.py b/dvc/command/base.py index 94874854b..6aa6b8dfa 100644 --- a/dvc/command/base.py +++ b/dvc/command/base.py @@ -51,11 +51,17 @@ class CmdBase(object): def set_skip_git_actions(self, parser): parser.add_argument('--skip-git-actions', '-s', action='store_true', help='Skip all git actions including reproducibility check and commits') + parser.add_argument('--no-lock', '-L', action='store_true', default=False, + help='Do not set DVC locker') @property def skip_git_actions(self): return self.parsed_args.skip_git_actions + @property + def is_locker(self): + return not self.parsed_args.no_lock + def commit_if_needed(self, message, error=False): if error or self.skip_git_actions: self.not_committed_changes_warning() diff --git a/dvc/command/data_import.py b/dvc/command/data_import.py index b4d161351..e2ee61ea8 100644 --- a/dvc/command/data_import.py +++ b/dvc/command/data_import.py @@ -36,11 +36,12 @@ class CmdDataImport(CmdBase): pass def run(self): - lock = fasteners.InterProcessLock(self.git.lock_file) - gotten = lock.acquire(timeout=5) - if not gotten: - Logger.info('Cannot perform the cmd since DVC is busy and locked. Please retry the cmd later.') - return 1 + if self.is_locker: + lock = fasteners.InterProcessLock(self.git.lock_file) + gotten = lock.acquire(timeout=5) + if not gotten: + Logger.info('Cannot perform the cmd since DVC is busy and locked. Please retry the cmd later.') + return 1 try: if not self.skip_git_actions and not self.git.is_ready_to_go(): @@ -53,7 +54,8 @@ class CmdDataImport(CmdBase): message = 'DVC data import: {} {}'.format(' '.join(self.parsed_args.input), self.parsed_args.output) return self.commit_if_needed(message) finally: - lock.release() + if self.is_locker: + lock.release() pass def import_file(self, input, output, is_reproducible): diff --git a/dvc/command/data_sync.py b/dvc/command/data_sync.py index 28aa3c817..678c5e165 100644 --- a/dvc/command/data_sync.py +++ b/dvc/command/data_sync.py @@ -2,6 +2,7 @@ import base64 import hashlib import os +import fasteners from boto.s3.connection import S3Connection from google.cloud import storage as gc @@ -46,14 +47,25 @@ class CmdDataSync(CmdBase): self.add_string_arg(parser, 'target', 'Target to sync - file or directory') def run(self): - if System.islink(self.parsed_args.target): - data_item = self.settings.path_factory.data_item(self.parsed_args.target) - return self.sync_symlink(data_item) + if self.is_locker: + lock = fasteners.InterProcessLock(self.git.lock_file) + gotten = lock.acquire(timeout=5) + if not gotten: + Logger.info('Cannot perform the cmd since DVC is busy and locked. Please retry the cmd later.') + return 1 - if os.path.isdir(self.parsed_args.target): - return self.sync_dir(self.parsed_args.target) + try: + if System.islink(self.parsed_args.target): + data_item = self.settings.path_factory.data_item(self.parsed_args.target) + return self.sync_symlink(data_item) - raise DataSyncError('File "{}" does not exit'.format(self.parsed_args.target)) + if os.path.isdir(self.parsed_args.target): + return self.sync_dir(self.parsed_args.target) + + raise DataSyncError('File "{}" does not exit'.format(self.parsed_args.target)) + finally: + if self.is_locker: + lock.release() def sync_dir(self, dir): for f in os.listdir(dir): diff --git a/dvc/command/remove.py b/dvc/command/remove.py index 426d358f8..cf3f8d001 100644 --- a/dvc/command/remove.py +++ b/dvc/command/remove.py @@ -30,17 +30,19 @@ class CmdDataRemove(CmdBase): pass def run(self): - lock = fasteners.InterProcessLock(self.git.lock_file) - gotten = lock.acquire(timeout=5) - if not gotten: - Logger.info('[Cmd-Remove] Cannot perform the cmd since DVC is busy and locked. Please retry the cmd later.') - return 1 + if self.is_locker: + lock = fasteners.InterProcessLock(self.git.lock_file) + gotten = lock.acquire(timeout=5) + if not gotten: + Logger.info('[Cmd-Remove] Cannot perform the cmd since DVC is busy and locked. Please retry the cmd later.') + return 1 try: if not self.remove_all_targets(): return 1 finally: - lock.release() + if self.is_locker: + lock.release() return 0 diff --git a/dvc/command/repro.py b/dvc/command/repro.py index bb4278732..c6cbf5aa1 100644 --- a/dvc/command/repro.py +++ b/dvc/command/repro.py @@ -46,16 +46,18 @@ class CmdRepro(CmdRun): return [] def run(self): - lock = fasteners.InterProcessLock(self.git.lock_file) - gotten = lock.acquire(timeout=5) - if not gotten: - self.warning_dvc_is_busy() - return 1 + if self.is_locker: + lock = fasteners.InterProcessLock(self.git.lock_file) + gotten = lock.acquire(timeout=5) + if not gotten: + self.warning_dvc_is_busy() + return 1 try: return self.repro_target(self.parsed_args.target, self.parsed_args.force) finally: - lock.release() + if self.is_locker: + lock.release() pass diff --git a/dvc/command/run.py b/dvc/command/run.py index d6ffb29b6..0654d1b7c 100644 --- a/dvc/command/run.py +++ b/dvc/command/run.py @@ -54,11 +54,12 @@ class CmdRun(CmdBase): return self._data_items_from_params(self.parsed_args.output, 'Output') def run(self): - lock = fasteners.InterProcessLock(self.git.lock_file) - gotten = lock.acquire(timeout=5) - if not gotten: - self.warning_dvc_is_busy() - return 1 + if self.is_locker: + lock = fasteners.InterProcessLock(self.git.lock_file) + gotten = lock.acquire(timeout=5) + if not gotten: + self.warning_dvc_is_busy() + return 1 try: if not self.skip_git_actions and not self.git.is_ready_to_go(): @@ -71,9 +72,8 @@ class CmdRun(CmdBase): self.parsed_args.shell) return self.commit_if_needed('DVC run: {}'.format(' '.join(self.args))) finally: - lock.release() - - return 1 + if self.is_locker: + lock.release() def run_command(self, cmd_args, data_items_from_args, stdout=None, stderr=None, shell=False): Logger.debug('Run command with args: {}. Data items from args: {}. stdout={}, stderr={}, shell={}'.format(