mirrorfile 0.1.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b29787fe3ec7d699137a8bc8f02dbfafd0ac95693dece15bf7199c977d3aa0e
4
- data.tar.gz: df9541b78b01255029986e18f3144294f4e60b436b8d928c7e8ff8937177cadc
3
+ metadata.gz: 513175ce2e6de6e4e0a0a810d844ce5a280fd3e899cf490b289249054a8c37f9
4
+ data.tar.gz: 9a8ca82bdd368ef020c97fbf156aba1e5d3cad6860e5eef4e02226165c167277
5
5
  SHA512:
6
- metadata.gz: b3fd0d4747c159d0cf957012a7ba997b0dfc062278ef5d3b0b0bd823e23e96df11d78ebd863a1dbfe91beabac0a8e1a207e84cdbca662c0d2fa70a2ef5706172
7
- data.tar.gz: b0fea1083d5ec020119d35d775d19545662223110306e0ac6ce87598c80bc190a952dcb4113ed7f056845b0074651097b17add026c7743f90cbdc23ac1b1895c
6
+ metadata.gz: 0046b1bde5286137d682244bf597e8f72a0d43a206c6013b4dc470b08b9dead8ebbe0d7aa390c63437330b9ccf15c93dbefc99ca8e5a0bd346606166232f38b9
7
+ data.tar.gz: fa70c541f5cdaa6e17c2a654bf07a094cb2037a405409a9fda00fe8f7d725331cb6b66737915fe1df8b39a2f7c8bdbe4bcd887a1a536fd7c1420fa8bcbbdd971
data/.envrc ADDED
@@ -0,0 +1 @@
1
+ use flake
data/README.md CHANGED
@@ -22,7 +22,7 @@ gem install mirrorfile
22
22
 
23
23
  ## Usage
24
24
  ```bash
25
- mirror init # creates Mirrorfile, .gitignore entry, zeitwerk initializer
25
+ mirror init # creates Mirrorfile, .gitignore entry, zeitwerk initializer (Rails only)
26
26
  mirror install # clones missing repos
27
27
  mirror update # pulls existing repos
28
28
  mirror list # shows defined mirrors
data/flake.lock ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "nodes": {
3
+ "flake-utils": {
4
+ "inputs": {
5
+ "systems": "systems"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1731533236,
9
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10
+ "owner": "numtide",
11
+ "repo": "flake-utils",
12
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "numtide",
17
+ "repo": "flake-utils",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nixpkgs": {
22
+ "locked": {
23
+ "lastModified": 1772773019,
24
+ "narHash": "sha256-E1bxHxNKfDoQUuvriG71+f+s/NT0qWkImXsYZNFFfCs=",
25
+ "owner": "nixos",
26
+ "repo": "nixpkgs",
27
+ "rev": "aca4d95fce4914b3892661bcb80b8087293536c6",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "nixos",
32
+ "ref": "nixos-unstable",
33
+ "repo": "nixpkgs",
34
+ "type": "github"
35
+ }
36
+ },
37
+ "root": {
38
+ "inputs": {
39
+ "flake-utils": "flake-utils",
40
+ "nixpkgs": "nixpkgs"
41
+ }
42
+ },
43
+ "systems": {
44
+ "locked": {
45
+ "lastModified": 1681028828,
46
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
47
+ "owner": "nix-systems",
48
+ "repo": "default",
49
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
50
+ "type": "github"
51
+ },
52
+ "original": {
53
+ "owner": "nix-systems",
54
+ "repo": "default",
55
+ "type": "github"
56
+ }
57
+ }
58
+ },
59
+ "root": "root",
60
+ "version": 7
61
+ }
data/flake.nix ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ inputs = {
3
+ nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
4
+
5
+ flake-utils.url = "github:numtide/flake-utils";
6
+ flake-utils.inputs.nixpkgs.follows = "nixpkgs";
7
+ };
8
+
9
+ outputs = { self, nixpkgs, flake-utils }:
10
+ flake-utils.lib.eachDefaultSystem (system:
11
+ let
12
+ pkgs = nixpkgs.legacyPackages.${system};
13
+ in
14
+ {
15
+ devShells.default = pkgs.mkShell {
16
+ packages = with pkgs; [
17
+ ruby_3_4
18
+ bundler
19
+ ];
20
+
21
+ shellHook = ''
22
+ export BUNDLE_PATH=".bundler"
23
+ export GEM_PATH=".bundler/ruby/3.4.0"
24
+
25
+ export PATH="$PWD/bin:$PATH"
26
+ export PATH=".bundler/ruby/3.4.0/bin:$PATH"
27
+ '';
28
+
29
+ };
30
+
31
+ packages.default = pkgs.hello;
32
+ }
33
+ );
34
+ }
@@ -21,7 +21,7 @@ module Mirrorfile
21
21
  class CLI
22
22
  # Available CLI commands
23
23
  # @return [Array<String>] list of valid commands
24
- COMMANDS = %w[init install update list help].freeze
24
+ COMMANDS = %w[init install update list git help].freeze
25
25
 
26
26
  # Creates a new CLI instance.
27
27
  #
@@ -48,15 +48,33 @@ module Mirrorfile
48
48
  def call(args)
49
49
  command = args.first
50
50
 
51
+ if legacy_command?(command) && Mirror.new.legacy?
52
+ return CLILegacy.new(stdout: @stdout, stderr: @stderr).call(args)
53
+ end
54
+
55
+ dispatch(args)
56
+ end
57
+
58
+ # Dispatches args to the appropriate command method.
59
+ #
60
+ # Separated from {#call} so that {CLILegacy} can dispatch
61
+ # without re-checking legacy state.
62
+ #
63
+ # @param args [Array<String>] command-line arguments
64
+ # @return [Integer] exit status code
65
+ def dispatch(args)
66
+ command = args.first
67
+
51
68
  case command
52
- when "init" then init
53
- when "install" then install
54
- when "update" then update
55
- when "list" then list
56
- when "help" then help
57
- when "-h", "--help" then help
58
- when "-v", "--version" then version
59
- else usage
69
+ when 'init' then init
70
+ when 'install' then install
71
+ when 'update' then update
72
+ when 'list' then list
73
+ when 'git' then git(args.drop(1))
74
+ when 'help' then help
75
+ when '-h', '--help' then help
76
+ when '-v', '--version' then version
77
+ else usage
60
78
  end
61
79
 
62
80
  0
@@ -65,12 +83,25 @@ module Mirrorfile
65
83
  1
66
84
  rescue StandardError => e
67
85
  @stderr.puts "Error: #{e.message}"
68
- @stderr.puts e.backtrace.first(5).map { " #{_1}" } if ENV["DEBUG"]
86
+ @stderr.puts(e.backtrace.first(5).map { " #{_1}" }) if ENV['DEBUG']
69
87
  1
70
88
  end
71
89
 
72
90
  private
73
91
 
92
+ # Returns whether the given command should use legacy mode
93
+ # when legacy mirrors are detected.
94
+ #
95
+ # Commands like init, help, and version flags are not affected
96
+ # by legacy state and always use the standard CLI.
97
+ #
98
+ # @param command [String, nil] the command name
99
+ # @return [Boolean]
100
+ # @api private
101
+ def legacy_command?(command)
102
+ %w[install update list git].include?(command)
103
+ end
104
+
74
105
  # Executes the init command.
75
106
  #
76
107
  # @return [void]
@@ -84,9 +115,9 @@ module Mirrorfile
84
115
  # @return [void]
85
116
  # @api private
86
117
  def install
87
- @stdout.puts "Installing mirrors..."
118
+ @stdout.puts 'Installing mirrors...'
88
119
  Mirror.new.install
89
- @stdout.puts "Done."
120
+ @stdout.puts 'Done.'
90
121
  end
91
122
 
92
123
  # Executes the update command.
@@ -94,9 +125,9 @@ module Mirrorfile
94
125
  # @return [void]
95
126
  # @api private
96
127
  def update
97
- @stdout.puts "Updating mirrors..."
128
+ @stdout.puts 'Updating mirrors...'
98
129
  Mirror.new.update
99
- @stdout.puts "Done."
130
+ @stdout.puts 'Done.'
100
131
  end
101
132
 
102
133
  # Executes the list command.
@@ -106,7 +137,19 @@ module Mirrorfile
106
137
  def list
107
138
  entries = Mirror.new.list
108
139
 
109
- entries.empty? ? @stdout.puts("No mirrors defined.") : entries.each { @stdout.puts _1 }
140
+ entries.empty? ? @stdout.puts('No mirrors defined.') : entries.each { @stdout.puts _1 }
141
+ end
142
+
143
+ # Executes a git command against a .git.mirror directory.
144
+ #
145
+ # Runs git with --git-dir=.git.mirror in the current working
146
+ # directory, passing through all additional arguments.
147
+ #
148
+ # @param args [Array<String>] arguments to pass to git
149
+ # @return [void]
150
+ # @api private
151
+ def git(args)
152
+ system('git', '--git-dir=.git.mirror', *args)
110
153
  end
111
154
 
112
155
  # Displays help information.
@@ -125,6 +168,7 @@ module Mirrorfile
125
168
  install Clone repositories that don't exist locally
126
169
  update Pull latest changes for existing repositories
127
170
  list Show all defined mirrors
171
+ git Run git commands against a .git.mirror directory
128
172
  help Show this help message
129
173
 
130
174
  Options:
@@ -135,6 +179,7 @@ module Mirrorfile
135
179
  $ mirror init
136
180
  $ mirror install
137
181
  $ mirror update
182
+ $ cd mirrors/rails && mirror git log --oneline
138
183
 
139
184
  Mirrorfile syntax:
140
185
  source "https://github.com"
@@ -155,7 +200,7 @@ module Mirrorfile
155
200
  # @return [void]
156
201
  # @api private
157
202
  def version
158
- @stdout.puts "mirrorfile #{Mirrorfile::VERSION}"
203
+ @stdout.puts "mirrorfile #{::Mirrorfile::VERSION}"
159
204
  end
160
205
 
161
206
  # Displays usage information for unknown commands.
@@ -167,10 +212,11 @@ module Mirrorfile
167
212
  Usage: mirror <command>
168
213
 
169
214
  Commands:
170
- init Create Mirrorfile, .gitignore entry, and Zeitwerk initializer
215
+ init Create Mirrorfile, .gitignore entry, and Zeitwerk initializer (Rails only)
171
216
  install Clone repositories that don't exist locally
172
217
  update Pull latest changes for existing repositories
173
218
  list Show all defined mirrors
219
+ git Run git commands against a .git.mirror directory
174
220
  help Show detailed help
175
221
 
176
222
  Run 'mirror help' for more information.
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mirrorfile
4
+ # Legacy CLI for projects with old-style .git directories.
5
+ #
6
+ # This CLI is used automatically when mirrorfile detects that the
7
+ # mirrors directory contains repositories with .git instead of
8
+ # .git.mirror. It prints a deprecation warning and operates using
9
+ # the legacy .git directory name.
10
+ #
11
+ # @see CLI
12
+ # @since 1.0.0
13
+ class CLILegacy < CLI
14
+ LEGACY_WARNING = <<~WARN
15
+ [mirrorfile] WARNING: Your mirrors use legacy .git directories.
16
+ Upgrade with mirrorfile v0.1.1 (`mirror migrate-to-v1`), or remove
17
+ the mirrors/ directory and re-run `mirror install`.
18
+ WARN
19
+
20
+ # Overrides CLI#call to skip legacy detection and dispatch directly.
21
+ #
22
+ # @param args [Array<String>] command-line arguments
23
+ # @return [Integer] exit status code
24
+ def call(args)
25
+ dispatch(args)
26
+ end
27
+
28
+ private
29
+
30
+ # Executes the install command in legacy mode.
31
+ #
32
+ # @return [void]
33
+ # @api private
34
+ def install
35
+ @stderr.puts LEGACY_WARNING
36
+ @stdout.puts 'Installing mirrors (legacy mode)...'
37
+ Mirror.new.install(legacy: true)
38
+ @stdout.puts 'Done.'
39
+ end
40
+
41
+ # Executes the update command in legacy mode.
42
+ #
43
+ # @return [void]
44
+ # @api private
45
+ def update
46
+ @stderr.puts LEGACY_WARNING
47
+ @stdout.puts 'Updating mirrors (legacy mode)...'
48
+ Mirror.new.update(legacy: true)
49
+ @stdout.puts 'Done.'
50
+ end
51
+
52
+ # Executes the list command with a legacy warning.
53
+ #
54
+ # @return [void]
55
+ # @api private
56
+ def list
57
+ @stderr.puts LEGACY_WARNING
58
+ super
59
+ end
60
+
61
+ # Executes a git command using the default .git directory.
62
+ #
63
+ # In legacy mode, mirrors have .git (not .git.mirror), so
64
+ # no --git-dir flag is needed.
65
+ #
66
+ # @param args [Array<String>] arguments to pass to git
67
+ # @return [void]
68
+ # @api private
69
+ def git(args)
70
+ @stderr.puts LEGACY_WARNING
71
+ system('git', *args)
72
+ end
73
+ end
74
+ end
@@ -41,7 +41,13 @@ module Mirrorfile
41
41
  # clone the repository once. If the local directory already exists,
42
42
  # no action is taken.
43
43
  #
44
+ # After cloning, the .git directory is renamed to the configured
45
+ # git_dir name (default: .git.mirror) so that the host project's
46
+ # git does not treat it as a nested repository.
47
+ #
44
48
  # @param base_dir [Pathname] the base directory to clone into
49
+ # @param git_dir [String] the git directory name to use
50
+ # (default: ".git.mirror", use ".git" for legacy mode)
45
51
  # @return [Boolean, nil] true if clone succeeded, false if failed,
46
52
  # nil if already exists
47
53
  #
@@ -49,9 +55,15 @@ module Mirrorfile
49
55
  # entry.install(Pathname.new("mirrors"))
50
56
  #
51
57
  # @see #update
52
- def install(base_dir)
58
+ def install(base_dir, git_dir: '.git.mirror')
53
59
  dir = local_path(base_dir)
54
- system("git", "clone", url, dir.to_s) unless dir.exist?
60
+ return if dir.exist?
61
+
62
+ return unless system('git', 'clone', url, dir.to_s)
63
+
64
+ return unless git_dir != '.git'
65
+
66
+ File.rename(dir.join('.git').to_s, dir.join(git_dir).to_s)
55
67
  end
56
68
 
57
69
  # Updates an existing repository by pulling the latest changes.
@@ -60,6 +72,8 @@ module Mirrorfile
60
72
  # If the local directory doesn't exist, no action is taken.
61
73
  #
62
74
  # @param base_dir [Pathname] the base directory containing the clone
75
+ # @param git_dir [String] the git directory name to use
76
+ # (default: ".git.mirror", use ".git" for legacy mode)
63
77
  # @return [Boolean, nil] true if pull succeeded, false if failed,
64
78
  # nil if directory doesn't exist
65
79
  #
@@ -67,9 +81,12 @@ module Mirrorfile
67
81
  # entry.update(Pathname.new("mirrors"))
68
82
  #
69
83
  # @see #install
70
- def update(base_dir)
84
+ def update(base_dir, git_dir: '.git.mirror')
71
85
  dir = local_path(base_dir)
72
- system("git", "-C", dir.to_s, "pull", "--ff-only") if dir.exist?
86
+ return unless dir.exist?
87
+
88
+ system('git', '--git-dir', dir.join(git_dir).to_s,
89
+ '--work-tree', dir.to_s, 'pull', '--ff-only')
73
90
  end
74
91
 
75
92
  # Returns a human-readable representation of the entry.
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'fileutils'
4
+
3
5
  module Mirrorfile
4
6
  # Orchestrates mirror operations: init, install, and update.
5
7
  #
@@ -46,10 +48,10 @@ module Mirrorfile
46
48
  # mirror = Mirrorfile::Mirror.new(root: "/path/to/project")
47
49
  def initialize(root: Dir.pwd)
48
50
  @root = Pathname.new(root)
49
- @mirrors_dir = @root.join("mirrors")
50
- @gitignore_path = @root.join(".gitignore")
51
- @mirrorfile_path = @root.join("Mirrorfile")
52
- @initializer_path = @root.join("config/initializers/mirrors.rb")
51
+ @mirrors_dir = @root.join('mirrors')
52
+ @gitignore_path = @root.join('.gitignore')
53
+ @mirrorfile_path = @root.join('Mirrorfile')
54
+ @initializer_path = @root.join('config/initializers/mirrors.rb')
53
55
  @mirrorfile = load_mirrorfile if @mirrorfile_path.exist?
54
56
  end
55
57
 
@@ -66,10 +68,11 @@ module Mirrorfile
66
68
  # mirror.install
67
69
  #
68
70
  # @see Entry#install
69
- def install
71
+ def install(legacy: false)
70
72
  ensure_mirrorfile!
71
73
  mirrors_dir.mkpath
72
- @mirrorfile.entries.each { _1.install(mirrors_dir) }
74
+ git_dir = legacy ? '.git' : '.git.mirror'
75
+ @mirrorfile.entries.each { _1.install(mirrors_dir, git_dir: git_dir) }
73
76
  end
74
77
 
75
78
  # Updates all existing local repositories.
@@ -86,9 +89,10 @@ module Mirrorfile
86
89
  # mirror.update
87
90
  #
88
91
  # @see Entry#update
89
- def update
92
+ def update(legacy: false)
90
93
  ensure_mirrorfile!
91
- @mirrorfile.entries.each { _1.update(mirrors_dir) }
94
+ git_dir = legacy ? '.git' : '.git.mirror'
95
+ @mirrorfile.entries.each { _1.update(mirrors_dir, git_dir: git_dir) }
92
96
  end
93
97
 
94
98
  # Initializes a new project with mirror support.
@@ -98,7 +102,7 @@ module Mirrorfile
98
102
  #
99
103
  # - Creates a Mirrorfile with example syntax
100
104
  # - Adds /mirrors to .gitignore (creates file if needed)
101
- # - Creates a Rails initializer for Zeitwerk autoloading
105
+ # - Creates a Rails initializer for Zeitwerk autoloading (Rails projects only)
102
106
  #
103
107
  # Existing files are not overwritten.
104
108
  #
@@ -115,6 +119,7 @@ module Mirrorfile
115
119
  def init
116
120
  create_mirrorfile
117
121
  setup_gitignore
122
+ setup_templates
118
123
  setup_zeitwerk
119
124
  puts "Initialized mirrors in #{root}"
120
125
  end
@@ -131,6 +136,20 @@ module Mirrorfile
131
136
  @mirrorfile.entries.to_a
132
137
  end
133
138
 
139
+ # Returns whether any mirrors use legacy .git directories.
140
+ #
141
+ # A project is considered legacy if any subdirectory of mirrors/
142
+ # contains a .git directory without a .git.mirror sibling.
143
+ #
144
+ # @return [Boolean] true if legacy mirrors are detected
145
+ def legacy?
146
+ return false unless mirrors_dir.exist?
147
+
148
+ mirrors_dir.children.select(&:directory?).any? do |path|
149
+ path.join('.git').exist? && !path.join('.git.mirror').exist?
150
+ end
151
+ end
152
+
134
153
  private
135
154
 
136
155
  # Loads and parses the Mirrorfile.
@@ -195,10 +214,10 @@ module Mirrorfile
195
214
  # @return [Integer, nil] bytes written or nil if already ignored
196
215
  # @api private
197
216
  def setup_gitignore
198
- gitignore_path.exist? || gitignore_path.write("")
217
+ gitignore_path.exist? || gitignore_path.write('')
199
218
 
200
219
  lines = gitignore_path.readlines.map(&:chomp)
201
- lines.include?("/mirrors") || gitignore_path.write([*lines, "/mirrors"].join("\n") + "\n")
220
+ lines.include?('/mirrors') || gitignore_path.write([*lines, '/mirrors'].join("\n") + "\n")
202
221
  end
203
222
 
204
223
  # Creates a Rails initializer for Zeitwerk autoloading.
@@ -211,6 +230,8 @@ module Mirrorfile
211
230
  # @return [Integer, nil] bytes written or nil if file exists
212
231
  # @api private
213
232
  def setup_zeitwerk
233
+ return unless rails_project?
234
+
214
235
  initializer_path.dirname.mkpath
215
236
  initializer_path.exist? || initializer_path.write(<<~RUBY)
216
237
  # frozen_string_literal: true
@@ -231,5 +252,34 @@ module Mirrorfile
231
252
  end
232
253
  RUBY
233
254
  end
255
+
256
+ # Copies template files into the mirrors directory.
257
+ #
258
+ # Creates the mirrors directory if it doesn't exist, then copies
259
+ # envrc.template and README.md.template from the gem's
260
+ # templates directory. Existing files are not overwritten.
261
+ #
262
+ # @return [void]
263
+ # @api private
264
+ def setup_templates
265
+ mirrors_dir.mkpath
266
+
267
+ templates_dir = Pathname.new(__dir__).join('../../templates')
268
+
269
+ envrc_dest = mirrors_dir.join('.envrc')
270
+ envrc_dest.exist? || FileUtils.cp(templates_dir.join('envrc.template'), envrc_dest)
271
+
272
+ readme_dest = mirrors_dir.join('README.md')
273
+ readme_dest.exist? || FileUtils.cp(templates_dir.join('README.md.template'), readme_dest)
274
+ end
275
+
276
+ # Determines if the current project is a Rails application by checking
277
+ # for the standard Rails application entrypoint.
278
+ #
279
+ # @return [Boolean] true if Rails project structure is detected
280
+ # @api private
281
+ def rails_project?
282
+ root.join('config/application.rb').exist?
283
+ end
234
284
  end
235
285
  end
@@ -3,5 +3,5 @@
3
3
  module Mirrorfile
4
4
  # Current version of the Mirrorfile gem
5
5
  # @return [String] the semantic version string
6
- VERSION = "0.1.0"
6
+ VERSION = '1.0.0'
7
7
  end
data/lib/mirrorfile.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
3
+ require 'pathname'
4
4
 
5
- require_relative "mirrorfile/version"
6
- require_relative "mirrorfile/entry"
7
- require_relative "mirrorfile/mirrorfile"
8
- require_relative "mirrorfile/mirror"
9
- require_relative "mirrorfile/cli"
5
+ require_relative 'mirrorfile/version'
6
+ require_relative 'mirrorfile/entry'
7
+ require_relative 'mirrorfile/mirrorfile'
8
+ require_relative 'mirrorfile/mirror'
9
+ require_relative 'mirrorfile/cli'
10
+ require_relative 'mirrorfile/cli_legacy'
10
11
 
11
12
  # Mirrorfile is a gem for managing local mirrors of git repositories.
12
13
  #
@@ -49,14 +50,14 @@ module Mirrorfile
49
50
  #
50
51
  # @return [Pathname] path to the mirrors directory
51
52
  def mirrors_dir
52
- root.join("mirrors")
53
+ root.join('mirrors')
53
54
  end
54
55
 
55
56
  # Returns the path to the Mirrorfile
56
57
  #
57
58
  # @return [Pathname] path to the Mirrorfile
58
59
  def mirrorfile_path
59
- root.join("Mirrorfile")
60
+ root.join('Mirrorfile')
60
61
  end
61
62
  end
62
63
  end
@@ -0,0 +1,21 @@
1
+ # Mirrors
2
+
3
+ This directory contains mirrored git repositories managed by mirrorfile.
4
+
5
+ ## Working with git in mirrored repos
6
+
7
+ The `.git` directory in each mirrored repository is renamed to `.git.mirror`
8
+ to prevent the parent project from detecting them as submodules.
9
+
10
+ To run git commands within a mirror, use:
11
+
12
+ mirror git <command>
13
+
14
+ For example:
15
+
16
+ mirror git status
17
+ mirror git log --oneline
18
+
19
+ Alternatively, if you have [direnv](https://direnv.net/) installed, `cd` into
20
+ a mirror directory and the `.envrc` file will automatically set
21
+ `GIT_DIR=.git.mirror`, allowing you to use `git` commands directly.
@@ -0,0 +1,24 @@
1
+ # vim: set filetype=bash :
2
+ #
3
+ # This file can be utilised if `direnv` is installed.
4
+ # Alternatively, run the following helper:
5
+ #
6
+ # $ mirror git <any-git-command>
7
+ #
8
+ # $ mirror git status
9
+ # $ mirror git add .
10
+ # $ mirror git commit -m "example commit message"
11
+ #
12
+ # Direnv related resources:
13
+ # Docs - https://direnv.net/
14
+ # Packages - https://github.com/direnv
15
+ # Git - https://github.com/direnv/direnv
16
+ #
17
+ # This is needed because mirrorfile renames the `.git` directory to `.git.mirror`.
18
+ # This is essential to avoid issues with nested git repos that .gitignore can't solve.
19
+ # An example would be wanting to run `git add --force ./mirrors/example-project/flake.nix`.
20
+ # Unfortunately this doesn't work without removing the directory from .gitignore, which then means
21
+ # you have a submodule in your repo.
22
+ # By renaming the `.git` directory you avoid the parent repo detecting the folder as a submodule.
23
+
24
+ export GIT_DIR=.git.mirror
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mirrorfile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Kidd
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 1980-01-01 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: minitest
@@ -77,19 +77,25 @@ executables:
77
77
  extensions: []
78
78
  extra_rdoc_files: []
79
79
  files:
80
+ - ".envrc"
80
81
  - ".yardopts"
81
82
  - CHANGELOG.md
82
83
  - LICENSE.txt
83
84
  - README.md
84
85
  - Rakefile
85
86
  - exe/mirror
87
+ - flake.lock
88
+ - flake.nix
86
89
  - lib/mirrorfile.rb
87
90
  - lib/mirrorfile/cli.rb
91
+ - lib/mirrorfile/cli_legacy.rb
88
92
  - lib/mirrorfile/entry.rb
89
93
  - lib/mirrorfile/mirror.rb
90
94
  - lib/mirrorfile/mirrorfile.rb
91
95
  - lib/mirrorfile/version.rb
92
96
  - mirrorfile.gemspec
97
+ - templates/README.md.template
98
+ - templates/envrc.template
93
99
  homepage: https://github.com/n-at-han-k/mirrorfile
94
100
  licenses:
95
101
  - MIT
@@ -113,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
119
  - !ruby/object:Gem::Version
114
120
  version: '0'
115
121
  requirements: []
116
- rubygems_version: 3.6.7
122
+ rubygems_version: 3.7.2
117
123
  specification_version: 4
118
124
  summary: Manage local mirrors of git repositories
119
125
  test_files: []