git_tree 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 34ccd05ecc6f42587797fe03361bed486df6ba5591baaf3cefa715669c27f07f
4
+ data.tar.gz: 9f547d654742f88d5db2b2163299c3fda8152a5e257546d6aab23690b2f95f5f
5
+ SHA512:
6
+ metadata.gz: 1e87d794586327101150260f1d5942ba5d487b9f91b54d6db7a0d0d6e6a93e88952898704341d8643b4b3cd0f723e6ceb07e52a4d64b453198d280180bdaa755
7
+ data.tar.gz: 2144afb4d96f9f9dfc09e28a6d6caac5758a61c3f8bf108b236a28c7cda3c4efc6ba52a2a1e41c7765f3d7ab69a00c3ea63a6b3e6b1a33be103a491ace9a65c4
data/.rubocop.yml ADDED
@@ -0,0 +1,101 @@
1
+ require:
2
+ - rubocop-md
3
+ - rubocop-performance
4
+ - rubocop-rake
5
+ - rubocop-rspec
6
+
7
+ AllCops:
8
+ Exclude:
9
+ - demo/_site/**/*
10
+ - exe/**/*
11
+ - vendor/**/*
12
+ - Gemfile*
13
+ - git_tree.gemspec
14
+ NewCops: enable
15
+ TargetRubyVersion: 2.6
16
+
17
+ Gemspec/DeprecatedAttributeAssignment:
18
+ Enabled: false
19
+
20
+ Gemspec/RequireMFA:
21
+ Enabled: false
22
+
23
+ Layout/HashAlignment:
24
+ EnforcedColonStyle: table
25
+ EnforcedHashRocketStyle: table
26
+
27
+ Layout/InitialIndentation:
28
+ Exclude:
29
+ - README.md
30
+
31
+ Layout/LineLength:
32
+ Max: 150
33
+
34
+ Layout/MultilineMethodCallIndentation:
35
+ Enabled: false
36
+
37
+ Lint/RedundantCopDisableDirective:
38
+ Exclude:
39
+ - git_tree.gemspec
40
+
41
+ Metrics/AbcSize:
42
+ Max: 45
43
+
44
+ Metrics/BlockLength:
45
+ Exclude:
46
+ - git_tree.gemspec
47
+ - spec/**/*
48
+
49
+ Metrics/ClassLength:
50
+ Exclude:
51
+ - spec/**/*
52
+
53
+ Metrics/CyclomaticComplexity:
54
+ Max: 20
55
+
56
+ Metrics/MethodLength:
57
+ Max: 40
58
+
59
+ Metrics/PerceivedComplexity:
60
+ Max: 15
61
+
62
+ Naming/FileName:
63
+ Exclude:
64
+ - Rakefile
65
+
66
+ RSpec/ExampleLength:
67
+ Max: 20
68
+
69
+ RSpec/MultipleExpectations:
70
+ Max: 15
71
+
72
+ Style/CommandLiteral:
73
+ Enabled: false
74
+
75
+ Style/CommentedKeyword:
76
+ Enabled: false
77
+
78
+ Style/Documentation:
79
+ Enabled: false
80
+
81
+ Style/FrozenStringLiteralComment:
82
+ Enabled: false
83
+
84
+ Style/PercentLiteralDelimiters:
85
+ Enabled: false
86
+
87
+ Style/RegexpLiteral:
88
+ Enabled: false
89
+
90
+ Style/StringConcatenation:
91
+ Exclude:
92
+ - spec/**/*
93
+
94
+ Style/StringLiterals:
95
+ Enabled: false
96
+
97
+ Style/StringLiteralsInInterpolation:
98
+ Enabled: false
99
+
100
+ Style/TrailingCommaInHashLiteral:
101
+ EnforcedStyleForMultiline: comma
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ ## 0.2.0 / 2023-05-02
2
+ * Renamed gem to `git_tree`
3
+ * Renamed `replicate_git_tree` command to `git_tree_replicate`.
4
+ * Added `.evars` support with new executable: `git_tree_evars`
5
+ * Added support for a symlinked root directory
6
+
7
+ ## 0.1.3 / 2023-05-01
8
+ * Fussing with directory path (works!!!)
9
+
10
+ ## 0.1.2 / 2023-05-01
11
+ * Fussing with gem executable (did not work)
12
+
13
+ ## 0.1.1 / 2023-05-01
14
+ * Added missing file (did not work)
15
+
16
+ ## 0.1.0 / 2023-05-01
17
+ * Published as a gem (did not work)
18
+
19
+ ## 2021-04-10
20
+ * Initial version published at https://www.mslinn.com/git/1100-git-tree.html
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Mike Slinn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,169 @@
1
+ `Git_tree`
2
+ [![Gem Version](https://badge.fury.io/rb/git_tree.svg)](https://badge.fury.io/rb/git_tree)
3
+ ===========
4
+
5
+ This Ruby gem installs two commands that scan a git directory tree and write out scripts.
6
+ Directories containing a file called `.ignore` are ignored.
7
+
8
+ - The `git_tree_replicate` command writes a script that clones the repos in the tree,
9
+ and adds any defined remotes.
10
+ - Any git repos that have already been cloned into the target directory tree are skipped.
11
+ This means you can rerun `git_tree_replicate` as many times as you want, without ill effects.
12
+ - All remotes in each repo are replicated.
13
+
14
+ - The `git_tree_evars` command writes a script that defines environment variables pointing to git repos.
15
+
16
+
17
+ ## Usage
18
+ Both commands requires only one parameter:
19
+ the name of the top-level directory to scan.
20
+
21
+ You must pass an environment variable to both commands.
22
+ Enclosing the name of the env var in single quotes,
23
+ which will prevent the shell from expanding it before invoking either command:
24
+
25
+ The following creates a script in the current directory called `work.sh`,
26
+ that replicates the desired portions of the directory tree of git repos pointed to by `$work`:
27
+ ```shell
28
+ $ git_tree_replicate '$work' > work.sh
29
+ ```
30
+
31
+ The generated environment variables will all be relative to the
32
+ env var you provided.
33
+ You will understand what this means once you try it and look at the generated script.
34
+
35
+ When `git_tree_replicate` completes,
36
+ edit the generated script to suit, then
37
+ copy it to the target machine and run it.
38
+ The following example copies the script to `machine2` and runs it:
39
+
40
+ ```shell
41
+ $ scp work.sh machine2:
42
+
43
+ $ ssh machine2 work.sh
44
+ ```
45
+
46
+
47
+ ### Generated Script from `git_tree_replicate`
48
+ Following is a sample of one section, which is repeated for every git repo that is processed:
49
+ You can edit them to suit.
50
+
51
+ ```shell
52
+ if [ ! -d "sinatra/sinatras-skeleton/.git" ]; then
53
+ mkdir -p 'sinatra'
54
+ pushd 'sinatra' > /dev/null
55
+ git clone git@github.com:mslinn/sinatras-skeleton.git
56
+ git remote add upstream 'https://github.com/simonneutert/sinatras-skeleton.git'
57
+ popd > /dev/null
58
+ fi
59
+ ```
60
+
61
+ ### Generated Script from `git_tree_evars`
62
+ Following is a sample of environment variable definitions.
63
+ You can edit it to suit.
64
+ Notice that it appends these environment variable definitions to `$work/.evars`.
65
+ You could cause it to replace the contents of that file by changing the `>>` to `>`.
66
+
67
+ ```shell
68
+ cat <<EOF >> $work/.evars
69
+ export work=/mnt/c/work
70
+ export ancientWarmth=$work/ancientWarmth/ancientWarmth
71
+ export ancientWarmthBackend=$work/ancientWarmth/ancientWarmthBackend
72
+ export braintreeTutorial=$work/ancientWarmth/braintreeTutorial
73
+ export survey_analytics=$work/ancientWarmth/survey-analytics
74
+ export survey_creator=$work/ancientWarmth/survey-creator
75
+ export django=$work/django/django
76
+ export frobshop=$work/django/frobshop
77
+ EOF
78
+ ```
79
+
80
+ The environment variable definitions are meant to be saved into a file that is `source`d upon boot.
81
+ While you could place them in a file like `~/.bashrc`,
82
+ the author's preference is to instead place them in `$work/.evars`,
83
+ and add the following to `~/.bashrc`:
84
+ ```shell
85
+ source "$work/.evars"
86
+ ```
87
+
88
+ Thus each time you log in, the environment variable definitions will have been re-established.
89
+ You can therefore change directory to any of the cloned projects, like this:
90
+ ```shell
91
+ $ cd $git_root
92
+
93
+ $ cd $my_project
94
+ ```
95
+
96
+
97
+ ## Installation
98
+ Type the following at a shell prompt:
99
+
100
+ ```ruby
101
+ $ gem install git_tree
102
+ ```
103
+
104
+
105
+ ## Additional Information
106
+ More information is available on
107
+ [Mike Slinn&rsquo;s website](https://www.mslinn.com/git/1100-git-tree.html)
108
+
109
+
110
+ ## Development
111
+ After checking out the repo, run `bin/setup` to install dependencies.
112
+
113
+ Run the following to create a directory tree for testing.
114
+ ```shell
115
+ $ ruby bin/make_test_directory.rb
116
+ ```
117
+
118
+ You can run `bin/console` for an interactive prompt that will allow you to experiment.
119
+ ```
120
+ $ bin/console
121
+ irb(main):001:0> GitTree.command_replicate 'demo'
122
+
123
+ irb(main):002:0> GitTree.command_evars 'demo'
124
+ ```
125
+
126
+
127
+ ### Build and Install Locally
128
+ To build and install this gem onto your local machine, run:
129
+ ```shell
130
+ $ bundle exec rake install
131
+ ```
132
+
133
+ Examine the newly built gem:
134
+ ```
135
+ $ gem info git_tree
136
+
137
+ *** LOCAL GEMS ***
138
+ git_tree (0.2.0)
139
+ Author: Mike Slinn
140
+ Homepage:
141
+ https://github.com/mslinn/git_tree_replicate
142
+ License: MIT
143
+ Installed at: /home/mslinn/.gems
144
+ ```
145
+
146
+
147
+ ### Build and Push to RubyGems
148
+ To release a new version,
149
+ 1. Update the version number in `version.rb`.
150
+ 2. Commit all changes to git; if you don't the next step might fail with an
151
+ unexplainable error message.
152
+ 3. Run the following:
153
+ ```shell
154
+ $ bundle exec rake release
155
+ ```
156
+ The above creates a git tag for the version, commits the created tag,
157
+ and pushes the new `.gem` file to [RubyGems.org](https://rubygems.org).
158
+
159
+
160
+ ## Contributing
161
+
162
+ 1. Fork the project
163
+ 2. Create a descriptively named feature branch
164
+ 3. Add your feature
165
+ 4. Submit a pull request
166
+
167
+
168
+ ## License
169
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task default: :spec
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'git_tree'
4
+
5
+ GitTree.command_evars
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'git_tree'
4
+
5
+ GitTree.command_replicate
data/git_tree.gemspec ADDED
@@ -0,0 +1,45 @@
1
+ require_relative 'lib/git_tree/version'
2
+
3
+ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
4
+ github = 'https://github.com/mslinn/git_tree'
5
+
6
+ spec.authors = ['Mike Slinn']
7
+ spec.bindir = 'bindir'
8
+ spec.description = <<~END_OF_DESC
9
+ Installs two commands that scan a git directory tree and write out scripts.
10
+ Directories containing a file called .ignore are ignored.
11
+ The git_tree_replicate command writes a script that clones the repos in the tree,
12
+ and adds any defined remotes.
13
+ The git_tree_evars command writes a script that defines environment variables pointing to git repos.
14
+ END_OF_DESC
15
+ spec.email = ['mslinn@mslinn.com']
16
+ spec.executables = %w[git_tree_evars git_tree_replicate]
17
+ spec.files = Dir[
18
+ '{bindir,lib}/**/*',
19
+ '.rubocop.yml',
20
+ 'LICENSE.*',
21
+ 'Rakefile',
22
+ '*.gemspec',
23
+ '*.md'
24
+ ]
25
+ spec.homepage = 'https://www.mslinn.com/git/1100-git-tree.html'
26
+ spec.license = 'MIT'
27
+ spec.metadata = {
28
+ 'allowed_push_host' => 'https://rubygems.org',
29
+ 'bug_tracker_uri' => "#{github}/issues",
30
+ 'changelog_uri' => "#{github}/CHANGELOG.md",
31
+ 'homepage_uri' => spec.homepage,
32
+ 'source_code_uri' => github,
33
+ }
34
+ spec.name = 'git_tree'
35
+ spec.post_install_message = <<~END_MESSAGE
36
+
37
+ Thanks for installing #{spec.name}!
38
+
39
+ END_MESSAGE
40
+ spec.required_ruby_version = '>= 2.6.0'
41
+ spec.summary = 'Installs two commands that scan a git directory tree and write out scripts for replication.'
42
+ spec.version = GitUrlsVersion::VERSION
43
+
44
+ spec.add_dependency 'rugged'
45
+ end
@@ -0,0 +1,3 @@
1
+ module GitUrlsVersion
2
+ VERSION = '0.2.0'.freeze
3
+ end
data/lib/git_tree.rb ADDED
@@ -0,0 +1,126 @@
1
+ module GitTree
2
+ require 'find'
3
+ require 'rugged'
4
+ require_relative 'util'
5
+
6
+ # @param root might be "$envar" or a fully qualified directory name ("/a/b/c")
7
+ def self.command_evars(root = ARGV[0])
8
+ abort "Error: Argument must start with a dollar sign ($)" unless root.start_with? '$'
9
+
10
+ base = MslinnUtil.expand_env root
11
+ dirs = directories_to_process base
12
+
13
+ # puts "# root=#{root}, base=#{base}"
14
+ puts make_env_vars root, base, dirs
15
+ end
16
+
17
+ # @param root might be "$envar" or a fully qualified directory name ("/a/b/c")
18
+ def self.command_replicate(root = ARGV[0])
19
+ abort "Error: Argument must start with a dollar sign ($)" unless root.start_with? '$'
20
+
21
+ base = MslinnUtil.expand_env root
22
+ dirs = directories_to_process base
23
+
24
+ # puts "# root=#{root}, base=#{base}"
25
+ puts make_replicate_script root, base, dirs
26
+ end
27
+
28
+ # @return array containing directory names to process
29
+ # Each directory name ends with a slash, to ensure symlinks are dereferences
30
+ def self.directories_to_process(root)
31
+ root_fq = File.expand_path root
32
+ abort "Error: #{root_fq} is a file, instead of a directory. Cannot recurse." if File.file? root_fq
33
+
34
+ root_fq = MslinnUtil.deref_symlink(root_fq).to_s
35
+ abort "Error: #{root_fq} does not exist. Halting." unless Dir.exist? root_fq
36
+
37
+ result = []
38
+ Find.find(root_fq) do |path|
39
+ next if File.file? path
40
+
41
+ Find.prune if File.exist?("#{path}/.ignore")
42
+
43
+ if Dir.exist?("#{path}/.git")
44
+ result << path.to_s
45
+ Find.prune
46
+ end
47
+ end
48
+ result.map { |x| x.delete_prefix("#{root_fq}/") }
49
+ end
50
+
51
+ def self.env_var_name(path)
52
+ name = path.include?('/') ? File.basename(path) : path
53
+ name.tr(' ', '_').tr('-', '_')
54
+ end
55
+
56
+ def self.help(msg = nil)
57
+ puts msg if msg
58
+ puts <<~END_HELP
59
+ Replicates tree of git repos and writes a bash script to STDOUT that clones the repos in the tree.
60
+ Adds upstream remotes as required.
61
+
62
+ Directories containing a file called .ignore are ignored.
63
+ END_HELP
64
+ exit 1
65
+ end
66
+
67
+ def self.make_env_var(name, value)
68
+ "export #{env_var_name(name)}=#{value}"
69
+ end
70
+
71
+ # @param root might be "$envar" or a fully qualified directory name ("/a/b/c")
72
+ # @param base a fully qualified directory name ("/a/b/c")
73
+ # @param dirs directory list to process
74
+ def self.make_env_vars(root, base, dirs)
75
+ result = []
76
+ result << "cat <<EOF >> #{root}/.evars"
77
+ result << make_env_var(env_var_name(base), MslinnUtil.deref_symlink(base))
78
+ dirs.each do |dir|
79
+ result << make_env_var(env_var_name(dir), "#{root}/#{dir}")
80
+ end
81
+ result << "EOF\n"
82
+ result.join "\n"
83
+ end
84
+
85
+ # @param root might be "$envar" or a fully qualified directory name ("/a/b/c")
86
+ # @param base a fully qualified directory name ("/a/b/c")
87
+ # @param dirs directory list to process
88
+ def self.make_replicate_script(root, base, dirs)
89
+ help "Error: Please specify the subdirectory to traverse.\n\n" if root.to_s.empty?
90
+
91
+ Dir.chdir(base) do
92
+ result = dirs.map { |dir| replicate_one(dir) }
93
+ result.join "\n"
94
+ end
95
+ end
96
+
97
+ def self.replicate_one(dir)
98
+ output = []
99
+ project_dir = File.basename dir
100
+ parent_dir = File.dirname dir
101
+ repo = Rugged::Repository.new dir
102
+ origin_url = repo.config['remote.origin.url']
103
+
104
+ output << "if [ ! -d \"#{dir}/.git\" ]; then"
105
+ output << " mkdir -p '#{parent_dir}'"
106
+ output << " pushd '#{parent_dir}' > /dev/null"
107
+ output << " git clone #{origin_url}"
108
+
109
+ repo.remotes.each do |remote|
110
+ next if remote.name == 'origin' || remote.url == 'no_push'
111
+
112
+ output << " git remote add #{remote.name} '#{remote.url}'"
113
+ end
114
+
115
+ output << ' popd > /dev/null'
116
+
117
+ # git_dir_name = File.basename Dir.pwd
118
+ # if git_dir_name != project_dir
119
+ # output << ' # Git project directory was renamed, renaming this copy to match original directory structure'
120
+ # output << " mv #{git_dir_name} #{project_dir}"
121
+ # end
122
+ output << "fi"
123
+ output << ''
124
+ output
125
+ end
126
+ end
data/lib/util.rb ADDED
@@ -0,0 +1,19 @@
1
+ module MslinnUtil
2
+ # @return Path to symlink
3
+ def self.deref_symlink(symlink)
4
+ require 'pathname'
5
+ Pathname.new(symlink).realpath
6
+ end
7
+
8
+ def self.ensure_ends_with(string, suffix)
9
+ string = string.delete_suffix suffix
10
+ "#{string}#{suffix}"
11
+ end
12
+
13
+ def self.expand_env(str)
14
+ str.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) do
15
+ ENV.fetch(Regexp.last_match(1), nil)
16
+ end
17
+ end
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git_tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Mike Slinn
8
+ autorequire:
9
+ bindir: bindir
10
+ cert_chain: []
11
+ date: 2023-05-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rugged
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: |
28
+ Installs two commands that scan a git directory tree and write out scripts.
29
+ Directories containing a file called .ignore are ignored.
30
+ The git_tree_replicate command writes a script that clones the repos in the tree,
31
+ and adds any defined remotes.
32
+ The git_tree_evars command writes a script that defines environment variables pointing to git repos.
33
+ email:
34
+ - mslinn@mslinn.com
35
+ executables:
36
+ - git_tree_evars
37
+ - git_tree_replicate
38
+ extensions: []
39
+ extra_rdoc_files: []
40
+ files:
41
+ - ".rubocop.yml"
42
+ - CHANGELOG.md
43
+ - LICENSE.txt
44
+ - README.md
45
+ - Rakefile
46
+ - bindir/git_tree_evars
47
+ - bindir/git_tree_replicate
48
+ - git_tree.gemspec
49
+ - lib/git_tree.rb
50
+ - lib/git_tree/version.rb
51
+ - lib/util.rb
52
+ homepage: https://www.mslinn.com/git/1100-git-tree.html
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ allowed_push_host: https://rubygems.org
57
+ bug_tracker_uri: https://github.com/mslinn/git_tree/issues
58
+ changelog_uri: https://github.com/mslinn/git_tree/CHANGELOG.md
59
+ homepage_uri: https://www.mslinn.com/git/1100-git-tree.html
60
+ source_code_uri: https://github.com/mslinn/git_tree
61
+ post_install_message: |2+
62
+
63
+ Thanks for installing git_tree!
64
+
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 2.6.0
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.3.3
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Installs two commands that scan a git directory tree and write out scripts
83
+ for replication.
84
+ test_files: []
85
+ ...