isomorphic-git 1.38.3 → 1.38.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -698,6 +698,18 @@ function dirname(path) {
698
698
  * This code for `path.join` is directly copied from @zenfs/core/path for bundle size improvements.
699
699
  * SPDX-License-Identifier: LGPL-3.0-or-later
700
700
  * Copyright (c) James Prevett and other ZenFS contributors.
701
+ *
702
+ * Windows support added:
703
+ * - Backslashes are normalised to forward slashes before processing.
704
+ * - Drive-letter prefixes (e.g. "C:") are detected and preserved through
705
+ * normalisation, so absolute Windows paths are handled correctly.
706
+ * - An absolute argument passed to join() resets the accumulated path,
707
+ * matching Node behaviour and handling worktree gitdir paths properly.
708
+ *
709
+ * Limitation: UNC paths (e.g. \\server\share) are not supported. The leading
710
+ * backslashes are normalised to forward slashes and then collapsed by
711
+ * normalizeString, losing the UNC root. Git on Windows works with
712
+ * drive-letter paths, so this is not expected to be a practical issue.
701
713
  */
702
714
 
703
715
  function normalizeString(path, aar) {
@@ -761,29 +773,67 @@ function normalizeString(path, aar) {
761
773
  return res
762
774
  }
763
775
 
776
+ // Returns the Windows drive prefix ("C:") if present, otherwise null.
777
+ function getWindowsDrivePrefix(path) {
778
+ if (path.length >= 2 && /^[a-zA-Z]:/.test(path)) {
779
+ return path.slice(0, 2) // e.g. "C:"
780
+ }
781
+ return null
782
+ }
783
+
764
784
  function normalize(path) {
765
785
  if (!path.length) return '.'
766
786
 
767
- const isAbsolute = path[0] === '/';
787
+ // Normalise backslashes to forward slashes before any other processing.
788
+ path = path.replace(/\\/g, '/');
789
+
790
+ const drivePrefix = getWindowsDrivePrefix(path);
791
+ // isAbsolute: Unix root ('/foo') OR Windows drive+slash ('C:/foo').
792
+ const isAbsolute =
793
+ path[0] === '/' || (drivePrefix !== null && path[2] === '/');
768
794
  const trailingSeparator = path.at(-1) === '/';
769
795
 
770
- path = normalizeString(path, !isAbsolute);
796
+ // Strip the drive prefix before feeding into normalizeString so that the
797
+ // core algorithm only ever sees a plain POSIX-style string.
798
+ const pathBody = drivePrefix ? path.slice(2) : path;
799
+
800
+ let normalized = normalizeString(pathBody, !isAbsolute);
771
801
 
772
- if (!path.length) {
773
- if (isAbsolute) return '/'
774
- return trailingSeparator ? './' : '.'
802
+ if (!normalized.length) {
803
+ const root = drivePrefix
804
+ ? isAbsolute
805
+ ? drivePrefix + '/'
806
+ : drivePrefix
807
+ : isAbsolute
808
+ ? '/'
809
+ : '.';
810
+ return trailingSeparator && !isAbsolute ? root + '/' : root
775
811
  }
776
- if (trailingSeparator) path += '/';
812
+ if (trailingSeparator) normalized += '/';
777
813
 
778
- return isAbsolute ? `/${path}` : path
814
+ if (drivePrefix) {
815
+ return isAbsolute
816
+ ? `${drivePrefix}/${normalized}`
817
+ : `${drivePrefix}${normalized}`
818
+ }
819
+ return isAbsolute ? `/${normalized}` : normalized
779
820
  }
780
821
 
781
822
  function join(...args) {
782
823
  if (args.length === 0) return '.'
783
824
  let joined;
784
825
  for (let i = 0; i < args.length; ++i) {
785
- const arg = args[i];
786
- if (arg.length > 0) {
826
+ // Normalise separators before processing.
827
+ const arg = args[i].replace(/\\/g, '/');
828
+ if (arg.length === 0) continue
829
+
830
+ // A Windows drive-letter path (e.g. "C:/worktrees/foo") cannot be
831
+ // meaningfully appended to any base, so it resets the accumulator.
832
+ // Unix absolute paths (leading '/') are NOT reset here — that would be
833
+ // path.resolve() semantics; path.join('foo', '/bar') must yield 'foo/bar'.
834
+ if (/^[a-zA-Z]:\//.test(arg)) {
835
+ joined = arg;
836
+ } else {
787
837
  if (joined === undefined) joined = arg;
788
838
  else joined += '/' + arg;
789
839
  }
package/managers/index.js CHANGED
@@ -691,6 +691,18 @@ function dirname(path) {
691
691
  * This code for `path.join` is directly copied from @zenfs/core/path for bundle size improvements.
692
692
  * SPDX-License-Identifier: LGPL-3.0-or-later
693
693
  * Copyright (c) James Prevett and other ZenFS contributors.
694
+ *
695
+ * Windows support added:
696
+ * - Backslashes are normalised to forward slashes before processing.
697
+ * - Drive-letter prefixes (e.g. "C:") are detected and preserved through
698
+ * normalisation, so absolute Windows paths are handled correctly.
699
+ * - An absolute argument passed to join() resets the accumulated path,
700
+ * matching Node behaviour and handling worktree gitdir paths properly.
701
+ *
702
+ * Limitation: UNC paths (e.g. \\server\share) are not supported. The leading
703
+ * backslashes are normalised to forward slashes and then collapsed by
704
+ * normalizeString, losing the UNC root. Git on Windows works with
705
+ * drive-letter paths, so this is not expected to be a practical issue.
694
706
  */
695
707
 
696
708
  function normalizeString(path, aar) {
@@ -754,29 +766,67 @@ function normalizeString(path, aar) {
754
766
  return res
755
767
  }
756
768
 
769
+ // Returns the Windows drive prefix ("C:") if present, otherwise null.
770
+ function getWindowsDrivePrefix(path) {
771
+ if (path.length >= 2 && /^[a-zA-Z]:/.test(path)) {
772
+ return path.slice(0, 2) // e.g. "C:"
773
+ }
774
+ return null
775
+ }
776
+
757
777
  function normalize(path) {
758
778
  if (!path.length) return '.'
759
779
 
760
- const isAbsolute = path[0] === '/';
780
+ // Normalise backslashes to forward slashes before any other processing.
781
+ path = path.replace(/\\/g, '/');
782
+
783
+ const drivePrefix = getWindowsDrivePrefix(path);
784
+ // isAbsolute: Unix root ('/foo') OR Windows drive+slash ('C:/foo').
785
+ const isAbsolute =
786
+ path[0] === '/' || (drivePrefix !== null && path[2] === '/');
761
787
  const trailingSeparator = path.at(-1) === '/';
762
788
 
763
- path = normalizeString(path, !isAbsolute);
789
+ // Strip the drive prefix before feeding into normalizeString so that the
790
+ // core algorithm only ever sees a plain POSIX-style string.
791
+ const pathBody = drivePrefix ? path.slice(2) : path;
792
+
793
+ let normalized = normalizeString(pathBody, !isAbsolute);
764
794
 
765
- if (!path.length) {
766
- if (isAbsolute) return '/'
767
- return trailingSeparator ? './' : '.'
795
+ if (!normalized.length) {
796
+ const root = drivePrefix
797
+ ? isAbsolute
798
+ ? drivePrefix + '/'
799
+ : drivePrefix
800
+ : isAbsolute
801
+ ? '/'
802
+ : '.';
803
+ return trailingSeparator && !isAbsolute ? root + '/' : root
768
804
  }
769
- if (trailingSeparator) path += '/';
805
+ if (trailingSeparator) normalized += '/';
770
806
 
771
- return isAbsolute ? `/${path}` : path
807
+ if (drivePrefix) {
808
+ return isAbsolute
809
+ ? `${drivePrefix}/${normalized}`
810
+ : `${drivePrefix}${normalized}`
811
+ }
812
+ return isAbsolute ? `/${normalized}` : normalized
772
813
  }
773
814
 
774
815
  function join(...args) {
775
816
  if (args.length === 0) return '.'
776
817
  let joined;
777
818
  for (let i = 0; i < args.length; ++i) {
778
- const arg = args[i];
779
- if (arg.length > 0) {
819
+ // Normalise separators before processing.
820
+ const arg = args[i].replace(/\\/g, '/');
821
+ if (arg.length === 0) continue
822
+
823
+ // A Windows drive-letter path (e.g. "C:/worktrees/foo") cannot be
824
+ // meaningfully appended to any base, so it resets the accumulator.
825
+ // Unix absolute paths (leading '/') are NOT reset here — that would be
826
+ // path.resolve() semantics; path.join('foo', '/bar') must yield 'foo/bar'.
827
+ if (/^[a-zA-Z]:\//.test(arg)) {
828
+ joined = arg;
829
+ } else {
780
830
  if (joined === undefined) joined = arg;
781
831
  else joined += '/' + arg;
782
832
  }