diff --git a/plugins/axiomcode/skills/axiomcode/scripts/ax_links.py b/plugins/axiomcode/skills/axiomcode/scripts/ax_links.py index b5054a3a..cbbad69a 100644 --- a/plugins/axiomcode/skills/axiomcode/scripts/ax_links.py +++ b/plugins/axiomcode/skills/axiomcode/scripts/ax_links.py @@ -1119,7 +1119,9 @@ def site_arg(repo, s): m = re.fullmatch(r'(.+?):(\d+)(?::(\d+))?', s or '') if not m: return None, None, None f = m.group(1) - if os.path.isabs(f): f = os.path.relpath(os.path.realpath(f), repo) + if os.path.isabs(f): + try: f = os.path.relpath(os.path.realpath(f), repo) + except ValueError: pass # another drive (Windows): not in this repository, kept as given f = f[2:] if f.startswith('./') else f return f.replace(os.sep, '/'), int(m.group(2)), (int(m.group(3)) if m.group(3) else None) diff --git a/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-changed b/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-changed index c367928e..90640391 100755 --- a/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-changed +++ b/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-changed @@ -413,7 +413,8 @@ class Changed: out.sort(); return out def rel(self, f): f = os.path.realpath(f) if os.path.exists(f) else f - r = os.path.relpath(f, self.repo) if os.path.isabs(f) else f + try: r = os.path.relpath(f, self.repo) if os.path.isabs(f) else f + except ValueError: r = f # another drive (Windows): outside the repository, kept as given return r.replace(os.sep, '/') # ── the two texts of a file ──────────────────────────────────────────────────────────────────────────────── def texts(self, rel, mode, rng): diff --git a/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-graph b/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-graph index 6ad4f249..59aa8c2e 100755 --- a/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-graph +++ b/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-graph @@ -91,7 +91,9 @@ def export(repo, page=None, how=''): def rel(p, src=src): a = p if os.path.isabs(p) else os.path.join(src, p) a = os.path.realpath(a) if os.path.exists(a) else os.path.normpath(a) - r = os.path.relpath(a, repo).replace(os.sep, '/'); return p.lstrip('/') if r.startswith('..') else r + try: r = os.path.relpath(a, repo).replace(os.sep, '/') + except ValueError: r = '..' # another drive (Windows): outside, as axiomcode-index reads it + return p.replace(os.sep, '/').lstrip('/') if r.startswith('..') else r # ── declarations: types and methods, with the display names the query skill uses when the index is there ── owners.update({r['id']: r['owner_type_id'] for r in q("SELECT id, owner_type_id FROM methods WHERE provenance='client'")}) diff --git a/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-index b/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-index index 9add01cd..8d260cab 100755 --- a/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-index +++ b/plugins/axiomcode/skills/axiomcode/scripts/axiomcode-index @@ -54,8 +54,12 @@ def rel(p): if not p: return p a = p if os.path.isabs(p) else os.path.join(SRC, p) a = os.path.realpath(a) if os.path.exists(a) else os.path.normpath(a) - r = os.path.relpath(a, REPO).replace(os.sep, '/') # '/' on every platform: every reader splits on it - return p.lstrip('/') if r.startswith('..') else r + # ON ANOTHER DRIVE (Windows) a path has no form relative to the repository: relpath raised, and a --library whose + # compiled IR sits in the user cache on C: while the repository is on D: failed the whole index. It is outside the + # repository, as a `..` path is, and is kept as written. + try: r = os.path.relpath(a, REPO).replace(os.sep, '/') # '/' on every platform: every reader splits on it + except ValueError: r = '..' + return p.replace(os.sep, '/').lstrip('/') if r.startswith('..') else r # never DEGRADE: an index built from the IR must not be rebuilt without it (the intermediates are routinely cleaned # to save disk). If only newer tables are missing, add them empty and keep everything else. prev = {r[0]: r[1] for r in c.execute("SELECT key, value FROM index_meta")} if c.execute("SELECT 1 FROM sqlite_master WHERE name='index_meta'").fetchone() else {} diff --git a/tests/no_exec.py b/tests/no_exec.py index 6c7e18f6..e227f3ea 100644 --- a/tests/no_exec.py +++ b/tests/no_exec.py @@ -79,7 +79,7 @@ def main(): open(os.path.join(site, 'sitecustomize.py'), 'w').write(WINDOWS_EXEC % SCRIPTS) plain = dict(os.environ) win = dict(plain, PYTHONPATH=site + os.pathsep + os.environ.get('PYTHONPATH', '')) - ax = ['bash', os.path.join(SCRIPTS, 'axiomcode')] + ax = [os.environ.get('AXIOMCODE_BASH') or 'bash', os.path.join(SCRIPTS, 'axiomcode')] # Windows: a bare `bash` is WSL's checks = [ # (why, argv, what the answer holds, exit status 0?) ('impact answers', ax + ['impact', 'Rates.rate', repo], 'Quote.total', True), ('impact --json answers', ax + ['impact', 'Rates.rate', repo, '--json'], '"Quote.total', True),