Module: GitTree

Defined in:
lib/git_tree.rb,
lib/git_tree_evars.rb,
lib/git_tree_replicate.rb

Class Method Summary collapse

Class Method Details

.command_evars(root = ARGV[0]) ⇒ Object

Parameters:

  • root (defaults to: ARGV[0])

    might be “$envar” or a fully qualified directory name (“/a/b/c”)



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/git_tree_evars.rb', line 7

def self.command_evars(root = ARGV[0])
  help_evars "Environment variable reference was missing. Please enclose it within single quotes." if root.to_s.empty?
  help_evars "Environment variable reference must start with a dollar sign ($)." unless root.start_with? '$'

  base = MslinnUtil.expand_env root
  help_evars "Environment variable '#{root}' is undefined." if base.strip.empty?
  help_evars "Environment variable '#{root}' points to a non-existant directory (#{base})." unless File.exist?(base)
  help_evars "Environment variable '#{root}' points to a file (#{base}), not a directory." unless Dir.exist?(base)

  dirs = directories_to_process base
  puts make_env_vars(root, base, dirs)
end

.command_replicate(root = ARGV[0]) ⇒ Object

Parameters:

  • root (defaults to: ARGV[0])

    might be “$envar” or a fully qualified directory name (“/a/b/c”)



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/git_tree_replicate.rb', line 7

def self.command_replicate(root = ARGV[0])
  help_replicate "Environment variable reference was missing. Please enclose it within single quotes." if root.to_s.empty?
  help_replicate "Error: Environment variable reference must start with a dollar sign ($)" unless root.start_with? '$'

  base = MslinnUtil.expand_env root
  help_replicate "Environment variable '#{root}' is undefined." if base.strip.empty?
  help_replicate "Environment variable '#{root}' points to a non-existant directory (#{base})." unless File.exist?(base)
  help_replicate "Environment variable '#{root}' points to a file (#{base}), not a directory." unless Dir.exist?(base)

  dirs = directories_to_process base
  puts make_replicate_script(root, base, dirs)
end

.directories_to_process(root) ⇒ Object

Returns array containing directory names to process Each directory name ends with a slash, to ensure symlinks are dereferences.

Returns:

  • array containing directory names to process Each directory name ends with a slash, to ensure symlinks are dereferences



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/git_tree.rb', line 11

def self.directories_to_process(root)
  root_fq = File.expand_path root
  abort "Error: #{root_fq} is a file, instead of a directory. Cannot recurse.".red if File.file? root_fq

  root_fq = MslinnUtil.deref_symlink(root_fq).to_s
  abort "Error: #{root_fq} does not exist. Halting.".red unless Dir.exist? root_fq

  result = []
  Find.find(root_fq) do |path|
    next if File.file? path

    Find.prune if File.exist?("#{path}/.ignore")

    if Dir.exist?("#{path}/.git")
      result << path.to_s
      Find.prune
    end
  end
  result.map { |x| x.delete_prefix("#{root_fq}/") }
end

.env_var_name(path) ⇒ Object



20
21
22
23
# File 'lib/git_tree_evars.rb', line 20

def self.env_var_name(path)
  name = path.include?('/') ? File.basename(path) : path
  name.tr(' ', '_').tr('-', '_')
end

.help_evars(msg = nil) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/git_tree_evars.rb', line 25

def self.help_evars(msg = nil)
  prog_name = File.basename $PROGRAM_NAME
  puts "Error: #{msg}\n".red if msg
  puts <<~END_HELP
    #{prog_name} - Examines a tree of git repositories and writes a bash script to STDOUT
    that defines environment variables which point to the repositories in the tree.

    Does not redefine existing environment variables; messages are written to
    STDERR to indicate environment variables that are not redefined.

    The environment variable must have been exported, for example:

    $ export work=$HOME/work

    Directories containing a file called .ignore are ignored.

    Usage example:

    $ #{prog_name} '$work'

    The name of the environment variable must be preceded by a dollar sign and enclosed within single quotes.
  END_HELP
  exit 1
end

.help_replicate(msg = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/git_tree_replicate.rb', line 20

def self.help_replicate(msg = nil)
  prog_name = File.basename $PROGRAM_NAME
  puts "Error: #{msg}\n".red if msg
  puts <<~END_HELP
    #{prog_name} - Replicates a tree of git repositories and writes a bash script
    to STDOUT that clones the repositories in the tree. Replicates any remotes
    defined in the source repositories to the target repositories.

    The environment variable must have been exported, for example:

    $ export work=$HOME/work

    Directories containing a file called .ignore are ignored.

    Usage example:
    Assuming that 'work' is an environment variable that contains the name of a
    directory that contains a tree of git repositories:

    $ #{prog_name} '$work'

    The name of the environment variable must be preceded by a dollar sign and enclosed within single quotes.
  END_HELP
  exit 1
end

.make_env_var(name, value) ⇒ Object



50
51
52
# File 'lib/git_tree_evars.rb', line 50

def self.make_env_var(name, value)
  "export #{env_var_name(name)}=#{value}"
end

.make_env_vars(root, base, dirs) ⇒ Object

Parameters:

  • root

    should be an “$envar” that points to the root of a directory tree containing git repos.

  • base

    a fully qualified directory name (“/a/b/c”)

  • dirs

    directory list to process



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/git_tree_evars.rb', line 57

def self.make_env_vars(root, base, dirs)
  help_evars "Error: Please specify the subdirectory to traverse." if root.to_s.empty?

  result = []
  result << make_env_var(env_var_name(base), MslinnUtil.deref_symlink(base))
  dirs.each do |dir|
    ename = env_var_name dir
    ename_value = MslinnUtil.expand_env "$#{ename}"
    ename_value = ename_value.gsub(' ', '\\ ').delete_prefix('\\') unless ename_value.empty?
    if ename_value.to_s.strip.empty?
      result << make_env_var(ename, "#{root}/#{dir}")
    else
      msg = "$#{ename} was previously defined as #{ename_value}"
      dir2 = MslinnUtil.expand_env(ename_value)
      if Dir.exist? dir2
        warn msg.cyan
      else
        msg += ", but that directory does not exist,\n  so redefining #{ename} as #{dir}."
        warn msg.green
        result << make_env_var(ename, "#{root}/#{dir}")
      end
    end
  end
  result.map { |x| "#{x}\n" }.join + "\n"
end

.make_replicate_script(root, base, dirs) ⇒ Object

Parameters:

  • root

    should be an “$envar” that points to the root of a directory tree containing git repos.

  • base

    a fully qualified directory name (“/a/b/c”)

  • dirs

    directory list to process



48
49
50
51
52
53
54
55
# File 'lib/git_tree_replicate.rb', line 48

def self.make_replicate_script(root, base, dirs)
  help_replicate "Error: Please specify the subdirectory to traverse.\n\n" if root.to_s.empty?

  Dir.chdir(base) do
    result = dirs.map { |dir| replicate_one(dir) }
    result.join "\n"
  end
end

.replicate_one(dir) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/git_tree_replicate.rb', line 57

def self.replicate_one(dir)
  output = []
  # project_dir = File.basename dir
  parent_dir = File.dirname dir
  repo = Rugged::Repository.new dir
  origin_url = repo.config['remote.origin.url']

  output << "if [ ! -d \"#{dir}/.git\" ]; then"
  output << "  mkdir -p '#{parent_dir}'"
  output << "  pushd '#{parent_dir}' > /dev/null"
  output << "  git clone #{origin_url}"

  repo.remotes.each do |remote|
    next if remote.name == 'origin' || remote.url == 'no_push'

    output << "  git remote add #{remote.name} '#{remote.url}'"
  end

  output << '  popd > /dev/null'

  # git_dir_name = File.basename Dir.pwd
  # if git_dir_name != project_dir
  #   output << '  # Git project directory was renamed, renaming this copy to match original directory structure'
  #   output << "  mv #{git_dir_name} #{project_dir}"
  # end
  output << 'fi'
  output << ''
  output
end