Make project pull order insensitive
@@ -27,14 +27,20 @@ def project_pull_cli(
def project_pull(project_dir: Path, remote: str, *, verbose: bool = False):
+ # TODO: We don't have tests for this :(. It would take a bit of mockery to
+ # set up. I guess see if it breaks first?
config = load_project_config(project_dir)
if remote in config.get("remotes", {}):
remote = config["remotes"][remote]
storage = RemoteStorage(project_dir, remote)
- for cmd in config.get("commands", []):
+ commands = list(config.get("commands", []))
+ # We use a while loop here because we don't know how the commands
+ # will be ordered. A command might need dependencies from one that's later
+ # in the list.
+ while commands:
+ for i, cmd in enumerate(list(commands)):
deps = [project_dir / dep for dep in cmd.get("deps", [])]
- if any(not dep.exists() for dep in deps):
- continue
+ if all(dep.exists() for dep in deps):
cmd_hash = get_command_hash("", "", deps, cmd["script"])
for output_path in cmd.get("outputs", []):
url = storage.pull(output_path, command_hash=cmd_hash)
@@ -43,3 +49,10 @@ def project_pull(project_dir: Path, remote: str, *, verbose: bool = False):
out_locs = [project_dir / out for out in cmd.get("outputs", [])]
if all(loc.exists() for loc in out_locs):
update_lockfile(project_dir, cmd)
+ # We remove the command from the list here, and break, so that
+ # we iterate over the loop again.
+ commands.remove(i)
+ break
+ else:
+ # If we didn't break the for loop, break the while loop.
+ break
