summary refs log tree commit diff
path: root/maintainers/scripts/update.py
diff options
context:
space:
mode:
authorJan Tojnar <jtojnar@gmail.com>2020-09-20 10:29:34 +0200
committerJan Tojnar <jtojnar@gmail.com>2020-09-20 20:12:34 +0200
commit71c246c7856eafe369d673aec4ecbf7568b50a9f (patch)
tree5737bdc958a4a1ca5e62afd6af1b81b811f114b1 /maintainers/scripts/update.py
parent0c5ddf335836c521215ecc9bfbb07ba45256a7df (diff)
downloadnixpkgs-71c246c7856eafe369d673aec4ecbf7568b50a9f.tar
nixpkgs-71c246c7856eafe369d673aec4ecbf7568b50a9f.tar.gz
nixpkgs-71c246c7856eafe369d673aec4ecbf7568b50a9f.tar.bz2
nixpkgs-71c246c7856eafe369d673aec4ecbf7568b50a9f.tar.lz
nixpkgs-71c246c7856eafe369d673aec4ecbf7568b50a9f.tar.xz
nixpkgs-71c246c7856eafe369d673aec4ecbf7568b50a9f.tar.zst
nixpkgs-71c246c7856eafe369d673aec4ecbf7568b50a9f.zip
maintainers/scripts/update.nix: Run update scripts from the worktree
`update.nix` extracts `passthru.updateScript` attributes in the main repo
and when they are relative paths (e.g. `./update.sh`), Nix will resolve them
to absolute paths in the main repo.

Update scripts can use $(dirname $0) to get the location of files they
should update but that would point to the main repo.
We want them to modify the appropriate git worktree instead
so we replace the prefix accordingly.

`git rev-parse --show-toplevel` will resolve symlinks but, fortunately,
Nix will do that as well, so the path will match:

https://github.com/NixOS/nixpkgs/pull/98304#issuecomment-695761754
Diffstat (limited to 'maintainers/scripts/update.py')
-rw-r--r--maintainers/scripts/update.py20
1 files changed, 15 insertions, 5 deletions
diff --git a/maintainers/scripts/update.py b/maintainers/scripts/update.py
index 74e36eaf80c..8cc2bcbd67c 100644
--- a/maintainers/scripts/update.py
+++ b/maintainers/scripts/update.py
@@ -5,6 +5,7 @@ import asyncio
 import contextlib
 import json
 import os
+import re
 import subprocess
 import sys
 import tempfile
@@ -30,16 +31,22 @@ async def check_subprocess(*args, **kwargs):
 
     return process
 
-async def run_update_script(merge_lock: asyncio.Lock, temp_dir: Optional[Tuple[str, str]], package: Dict, keep_going: bool):
+async def run_update_script(nixpkgs_root: str, merge_lock: asyncio.Lock, temp_dir: Optional[Tuple[str, str]], package: Dict, keep_going: bool):
     worktree: Optional[str] = None
 
+    update_script_command = package['updateScript']
+
     if temp_dir is not None:
         worktree, _branch = temp_dir
 
+        # Update scripts can use $(dirname $0) to get their location but we want to run
+        # their clones in the git worktree, not in the main nixpkgs repo.
+        update_script_command = map(lambda arg: re.sub(r'^{0}'.format(re.escape(nixpkgs_root)), worktree, arg), update_script_command)
+
     eprint(f" - {package['name']}: UPDATING ...")
 
     try:
-        update_process = await check_subprocess('env', f"UPDATE_NIX_ATTR_PATH={package['attrPath']}", *package['updateScript'], stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, cwd=worktree)
+        update_process = await check_subprocess('env', f"UPDATE_NIX_ATTR_PATH={package['attrPath']}", *update_script_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, cwd=worktree)
         update_info = await update_process.stdout.read()
 
         await merge_changes(merge_lock, package, update_info, temp_dir)
@@ -125,7 +132,7 @@ async def merge_changes(merge_lock: asyncio.Lock, package: Dict, update_info: st
     else:
         eprint(f" - {package['name']}: DONE.")
 
-async def updater(temp_dir: Optional[Tuple[str, str]], merge_lock: asyncio.Lock, packages_to_update: asyncio.Queue[Optional[Dict]], keep_going: bool, commit: bool):
+async def updater(nixpkgs_root: str, temp_dir: Optional[Tuple[str, str]], merge_lock: asyncio.Lock, packages_to_update: asyncio.Queue[Optional[Dict]], keep_going: bool, commit: bool):
     while True:
         package = await packages_to_update.get()
         if package is None:
@@ -135,7 +142,7 @@ async def updater(temp_dir: Optional[Tuple[str, str]], merge_lock: asyncio.Lock,
         if not ('commit' in package['supportedFeatures'] or 'attrPath' in package):
             temp_dir = None
 
-        await run_update_script(merge_lock, temp_dir, package, keep_going)
+        await run_update_script(nixpkgs_root, merge_lock, temp_dir, package, keep_going)
 
 async def start_updates(max_workers: int, keep_going: bool, commit: bool, packages: List[Dict]):
     merge_lock = asyncio.Lock()
@@ -147,6 +154,9 @@ async def start_updates(max_workers: int, keep_going: bool, commit: bool, packag
         # Do not create more workers than there are packages.
         num_workers = min(max_workers, len(packages))
 
+        nixpkgs_root_process = await check_subprocess('git', 'rev-parse', '--show-toplevel', stdout=asyncio.subprocess.PIPE)
+        nixpkgs_root = (await nixpkgs_root_process.stdout.read()).decode('utf-8').strip()
+
         # Set up temporary directories when using auto-commit.
         for i in range(num_workers):
             temp_dir = stack.enter_context(make_worktree()) if commit else None
@@ -163,7 +173,7 @@ async def start_updates(max_workers: int, keep_going: bool, commit: bool, packag
 
         # Prepare updater workers for each temp_dir directory.
         # At most `num_workers` instances of `run_update_script` will be running at one time.
-        updaters = asyncio.gather(*[updater(temp_dir, merge_lock, packages_to_update, keep_going, commit) for temp_dir in temp_dirs])
+        updaters = asyncio.gather(*[updater(nixpkgs_root, temp_dir, merge_lock, packages_to_update, keep_going, commit) for temp_dir in temp_dirs])
 
         try:
             # Start updater workers.