@@ -12,43 +12,35 @@ class Base
12
12
13
13
# (see Git.bare)
14
14
def self . bare ( git_dir , options = { } )
15
- self . new ( { :repository => git_dir } . merge ( options ) )
15
+ normalize_paths ( options , default_repository : git_dir , bare : true )
16
+ self . new ( options )
16
17
end
17
18
18
19
# (see Git.clone)
19
20
def self . clone ( repository , name , options = { } )
20
- self . new ( Git ::Lib . new ( nil , options [ :log ] ) . clone ( repository , name , options ) )
21
+ new_options = Git ::Lib . new ( nil , options [ :log ] ) . clone ( repository , name , options )
22
+ normalize_paths ( new_options , bare : options [ :bare ] || options [ :mirror ] )
23
+ self . new ( new_options )
21
24
end
22
25
23
26
# Returns (and initialize if needed) a Git::Config instance
24
27
#
25
28
# @return [Git::Config] the current config instance.
26
29
def self . config
27
- return @@config ||= Config . new
30
+ @@config ||= Config . new
28
31
end
29
32
30
33
# (see Git.init)
31
- def self . init ( directory , options = { } )
32
- options [ :working_directory ] ||= directory
33
- options [ :repository ] ||= File . join ( options [ :working_directory ] , '.git' )
34
-
35
- FileUtils . mkdir_p ( options [ :working_directory ] ) if options [ :working_directory ] && !File . directory? ( options [ :working_directory ] )
34
+ def self . init ( directory = '.' , options = { } )
35
+ normalize_paths ( options , default_working_directory : directory , default_repository : directory , bare : options [ :bare ] )
36
36
37
37
init_options = {
38
38
:bare => options [ :bare ] ,
39
39
:initial_branch => options [ :initial_branch ] ,
40
40
}
41
41
42
- options . delete ( :working_directory ) if options [ :bare ]
43
-
44
- # Submodules have a .git *file* not a .git folder.
45
- # This file's contents point to the location of
46
- # where the git refs are held (In the parent repo)
47
- if options [ :working_directory ] && File . file? ( File . join ( options [ :working_directory ] , '.git' ) )
48
- git_file = File . open ( '.git' ) . read [ 8 ..-1 ] . strip
49
- options [ :repository ] = git_file
50
- options [ :index ] = git_file + '/index'
51
- end
42
+ directory = options [ :bare ] ? options [ :repository ] : options [ :working_directory ]
43
+ FileUtils . mkdir_p ( directory ) unless File . exist? ( directory )
52
44
53
45
# TODO: this dance seems awkward: this creates a Git::Lib so we can call
54
46
# init so we can create a new Git::Base which in turn (ultimately)
@@ -66,21 +58,8 @@ def self.init(directory, options = {})
66
58
end
67
59
68
60
# (see Git.open)
69
- def self . open ( working_dir , options = { } )
70
- # TODO: move this to Git.open?
71
-
72
- options [ :working_directory ] ||= working_dir
73
- options [ :repository ] ||= File . join ( options [ :working_directory ] , '.git' )
74
-
75
- # Submodules have a .git *file* not a .git folder.
76
- # This file's contents point to the location of
77
- # where the git refs are held (In the parent repo)
78
- if options [ :working_directory ] && File . file? ( File . join ( options [ :working_directory ] , '.git' ) )
79
- git_file = File . open ( '.git' ) . read [ 8 ..-1 ] . strip
80
- options [ :repository ] = git_file
81
- options [ :index ] = git_file + '/index'
82
- end
83
-
61
+ def self . open ( working_dir , options = { } )
62
+ normalize_paths ( options , default_working_directory : working_dir )
84
63
self . new ( options )
85
64
end
86
65
@@ -571,7 +550,6 @@ def with_temp_working &blk
571
550
with_working ( temp_dir , &blk )
572
551
end
573
552
574
-
575
553
# runs git rev-parse to convert the objectish to a full sha
576
554
#
577
555
# @example
@@ -596,6 +574,93 @@ def current_branch
596
574
self . lib . branch_current
597
575
end
598
576
599
- end
577
+ private
578
+
579
+ # Normalize options before they are sent to Git::Base.new
580
+ #
581
+ # Updates the options parameter by setting appropriate values for the following keys:
582
+ # * options[:working_directory]
583
+ # * options[:repository]
584
+ # * options[:index]
585
+ #
586
+ # All three values will be set to absolute paths. An exception is that
587
+ # :working_directory will be set to nil if bare is true.
588
+ #
589
+ private_class_method def self . normalize_paths (
590
+ options , default_working_directory : nil , default_repository : nil , bare : false
591
+ )
592
+ normalize_working_directory ( options , default : default_working_directory , bare : bare )
593
+ normalize_repository ( options , default : default_repository , bare : bare )
594
+ normalize_index ( options )
595
+ end
596
+
597
+ # Normalize options[:working_directory]
598
+ #
599
+ # If working with a bare repository, set to `nil`.
600
+ # Otherwise, set to the first non-nil value of:
601
+ # 1. `options[:working_directory]`,
602
+ # 2. the `default` parameter, or
603
+ # 3. the current working directory
604
+ #
605
+ # Finally, if options[:working_directory] is a relative path, convert it to an absoluite
606
+ # path relative to the current directory.
607
+ #
608
+ private_class_method def self . normalize_working_directory ( options , default :, bare : false )
609
+ working_directory =
610
+ if bare
611
+ nil
612
+ else
613
+ File . expand_path ( options [ :working_directory ] || default || Dir . pwd )
614
+ end
600
615
616
+ options [ :working_directory ] = working_directory
617
+ end
618
+
619
+ # Normalize options[:repository]
620
+ #
621
+ # If working with a bare repository, set to the first non-nil value out of:
622
+ # 1. `options[:repository]`
623
+ # 2. the `default` parameter
624
+ # 3. the current working directory
625
+ #
626
+ # Otherwise, set to the first non-nil value of:
627
+ # 1. `options[:repository]`
628
+ # 2. `.git`
629
+ #
630
+ # Next, if options[:repository] refers to a *file* and not a *directory*, set
631
+ # options[:repository] to the contents of that file. This is the case when
632
+ # working with a submodule or a secondary working tree (created with git worktree
633
+ # add). In these cases the repository is actually contained/nested within the
634
+ # parent's repository directory.
635
+ #
636
+ # Finally, if options[:repository] is a relative path, convert it to an absolute
637
+ # path relative to:
638
+ # 1. the current directory if working with a bare repository or
639
+ # 2. the working directory if NOT working with a bare repository
640
+ #
641
+ private_class_method def self . normalize_repository ( options , default :, bare : false )
642
+ repository =
643
+ if bare
644
+ File . expand_path ( options [ :repository ] || default || Dir . pwd )
645
+ else
646
+ File . expand_path ( options [ :repository ] || '.git' , options [ :working_directory ] )
647
+ end
648
+
649
+ if File . file? ( repository )
650
+ repository = File . expand_path ( File . open ( repository ) . read [ 8 ..-1 ] . strip , options [ :working_directory ] )
651
+ end
652
+
653
+ options [ :repository ] = repository
654
+ end
655
+
656
+ # Normalize options[:index]
657
+ #
658
+ # If options[:index] is a relative directory, convert it to an absolute
659
+ # directory relative to the repository directory
660
+ #
661
+ private_class_method def self . normalize_index ( options )
662
+ index = File . expand_path ( options [ :index ] || 'index' , options [ :repository ] )
663
+ options [ :index ] = index
664
+ end
665
+ end
601
666
end
0 commit comments