git-reclone 0.2.3 → 1.0.1

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: 773ab4311def22ad7a61354f524f3439850a3b850a7d7d85478fb5ee50546de8
4
- data.tar.gz: 6bc7f99038ba912dc4f132d7e904807a39d1379621486249f743f5c3c0aefbe1
3
+ metadata.gz: 98a27fe2203a4ee3b2a3a59ceb3ee3dc3119b9f900238a8c7273307dea196730
4
+ data.tar.gz: 287d77e58954e169186dbca7c6c84867d8bf0130499252f77f581796a8015d65
5
5
  SHA512:
6
- metadata.gz: c6a5922718687dc8c61bdc899a084f731e0d8ab9db978e1a8b606f3bec13cae0cd7264f751316aeaf30221bf46a5f9b146161743f5f17945553090235d7f346c
7
- data.tar.gz: a5c29b46ea984b37bb6f6ecce064e5e760d286d9b064b488c053967fe49fe3f692c1ab943a121329c7bd7daf2a5e5e3a23d7bdf06a098714b25d9cbb3901660d
6
+ metadata.gz: 993b7033da1e2d1b9a9a6418abf842d11578ed5e60f04310b0d9400e406cd1886f1f05debf564a45ef990c0055bc7ce6ecfb44688dc9754b638dfeec1d50a188
7
+ data.tar.gz: 734de94a6cd4a524af501ad9381b20a95f9684af283f781623e8f048716cfa181cc8c44ecdf6289d8ef6e63fda5b8004ea2b1a121a70034ff445db70a9ba2daf
data/CHANGELOG.md ADDED
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-02-08
9
+
10
+ ### Added
11
+ - **Safe clone mechanism**: Repository now clones to a temporary directory first, only replacing the local copy after successful clone. This protects your local data if the clone fails for any reason.
12
+ - **Automatic branch restoration**: After recloning, the tool automatically checks out your original branch if it exists on the remote.
13
+ - **StandardRB linting**: Added StandardRB as a code linter with rake integration and Travis CI checks.
14
+ - **Comprehensive test suite**: Added tests for temp directory cleanup, failed clone handling, and branch restoration.
15
+ - **Modern git platform support**: Added support for Gitea and Gogs in addition to GitHub and Bitbucket.
16
+ - **Local assets**: Moved screencast from Imgur to local `assets/` folder in the repository.
17
+
18
+ ### Changed
19
+ - **Updated documentation**: Changed language from "destroy" to "replace" to better reflect the safer behavior.
20
+ - **Warning messages**: Updated user-facing messages to accurately describe the safe clone-to-temp-first approach.
21
+ - **Test repository**: Switched test suite to use GitHub's official `octocat/Hello-World` repository for better reliability.
22
+ - **Branch references**: Updated from `master` to `main` to reflect modern Git conventions.
23
+ - **Constant naming**: Renamed `Version` and `Help` to `VERSION` and `HELP` to follow Ruby naming conventions.
24
+ - **Gemspec improvements**:
25
+ - Added distinct summary and description
26
+ - Added bounded version constraints for all dependencies
27
+ - Improved description to highlight safety features
28
+
29
+ ### Removed
30
+ - **Ronn dependency**: Removed unused documentation generation dependency.
31
+ - **Heroku references**: Replaced with modern self-hosted Git platforms (Gitea, Gogs).
32
+
33
+ ### Fixed
34
+ - **Credential prompting**: Added `GIT_TERMINAL_PROMPT=0` to prevent interactive credential prompts during tests.
35
+ - **Test output**: Suppressed git clone progress output to keep test output clean.
36
+ - **All linting issues**: Fixed code style issues to comply with StandardRB.
37
+
38
+ ### Security
39
+ - **Safer reclone process**: Local repository is now preserved if remote clone fails, preventing data loss.
40
+
41
+ ## [0.2.3] - Previous Release
42
+ - Legacy version before major safety improvements
43
+
44
+ [1.0.0]: https://github.com/jeremywrnr/git-reclone/compare/v0.2.3...v1.0.0
data/bin/git-reclone CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "git-reclone"
4
+ require 'git_reclone'
4
5
 
5
6
  # git-reclone by jeremy warner
6
7
  # easily reset git repo from remotes
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # universal version tracking
2
4
 
3
5
  class GitReclone
4
- Version = "0.2.3"
6
+ VERSION = '1.0.1'
5
7
  end
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ # git-reclone gem
4
+ # jeremy warner
5
+
6
+ # TODO: add an option to automatically add a backup of the local copy
7
+ # todo: add all remotes other than the origins, maintain connections
8
+ # todo: -b / --backup, and this actually should be the default (maybe)
9
+
10
+ require 'colored'
11
+ require 'fileutils'
12
+ require 'tmpdir'
13
+ require_relative 'git_reclone/version'
14
+
15
+ class GitReclone
16
+ def initialize(test = false)
17
+ @pdelay = 0.01 # constant for arrow speed
18
+ @testing = test
19
+ @verify = !test
20
+ end
21
+
22
+ def fire(args = [])
23
+ opts = args.select { |a| a[0] == '-' }
24
+ opts.each { |o| parse_opt o }
25
+ exit 0 if @testing || opts.first
26
+ parse_arg((args - opts).first)
27
+ end
28
+
29
+ def pexit(msg)
30
+ puts msg
31
+ exit 1
32
+ end
33
+
34
+ def parse_opt(o)
35
+ case o
36
+ when '--force', '-f'
37
+ @verify = false
38
+ when '--help', '-h'
39
+ puts GitReclone::HELP
40
+ when '--version', '-v'
41
+ puts GitReclone::VERSION
42
+ end
43
+ end
44
+
45
+ def parse_arg(a)
46
+ a.nil? ? verify(remote) : verify(remote(a))
47
+ end
48
+
49
+ def no_repo?
50
+ `git status 2>&1`.split("\n").first ==
51
+ 'fatal: Not a git repository (or any of the parent directories): .git'
52
+ end
53
+
54
+ def git_root
55
+ `git rev-parse --show-toplevel`
56
+ end
57
+
58
+ def current_branch
59
+ `git rev-parse --abbrev-ref HEAD`.chomp
60
+ end
61
+
62
+ def remotes
63
+ `git remote -v`.split("\n").map { |r| r.split[1] }.uniq
64
+ end
65
+
66
+ def reclonebanner
67
+ 25.times { |x| slowp "\rpreparing| ".red << ('~' * x) << '#==>'.red }
68
+ 25.times { |x| slowp "\rpreparing| ".red << (' ' * x) << ('~' * (25 - x)) << '#==>'.yellow }
69
+ printf "\rREADY.".red << (' ' * 50) << "\n"
70
+ end
71
+
72
+ def slowp(x)
73
+ sleep @pdelay
74
+ printf x
75
+ end
76
+
77
+ # trying to parse out which remote should be the new source
78
+ def remote(search = /.*/)
79
+ pexit 'Not currently in a git repository.'.yellow if no_repo?
80
+
81
+ r = remotes.find { |gr| gr.match search }
82
+
83
+ pexit 'No remotes found in this repository.'.yellow if remotes.nil?
84
+
85
+ if r.nil?
86
+ errmsg = "No remotes found that match #{search.to_s.red}. All remotes:\n" + remotes.join("\n")
87
+ pexit errmsg
88
+ errmsg
89
+ else
90
+ r
91
+ end
92
+ end
93
+
94
+ # show remote to user and confirm location (unless using -f)
95
+ def verify(r)
96
+ reclonebanner
97
+ puts "Remote source:\t".red << r
98
+ puts "Local target:\t".red << git_root
99
+
100
+ branch = current_branch
101
+ puts "Current branch:\t".red << branch unless branch == 'HEAD'
102
+
103
+ if @verify
104
+ puts 'Warning: this will replace the local copy with a fresh clone from the remote.'.yellow
105
+ printf 'Continue recloning local repo? [yN] '.yellow
106
+ unless $stdin.gets.chomp.downcase[0] == 'y'
107
+ puts 'Reclone aborted.'.green
108
+ return
109
+ end
110
+ end
111
+
112
+ reclone remote, git_root.chomp, branch unless @testing
113
+ end
114
+
115
+ # overwrite the local copy of the repository with the remote one
116
+ def reclone(remote, root, branch = nil)
117
+ # create a temporary directory for cloning
118
+ temp_dir = Dir.mktmpdir('git-reclone-')
119
+
120
+ begin
121
+ # clone into temp directory (disable credential prompts)
122
+ cloner = "GIT_TERMINAL_PROMPT=0 git clone \"#{remote}\" \"#{temp_dir}\" > /dev/null 2>&1"
123
+
124
+ if system(cloner)
125
+ # clone succeeded, now replace the local copy
126
+ unless @testing
127
+ tree = Dir.glob('*', File::FNM_DOTMATCH).reject { |d| ['.', '..'].include? d }
128
+ FileUtils.rmtree(tree)
129
+
130
+ # move contents from temp to root
131
+ Dir.glob("#{temp_dir}/*", File::FNM_DOTMATCH).each do |item|
132
+ next if ['.', '..'].include?(File.basename(item))
133
+
134
+ FileUtils.mv(item, root)
135
+ end
136
+
137
+ # restore original branch if it exists
138
+ if branch && branch != 'HEAD'
139
+ Dir.chdir(root) do
140
+ system("git checkout #{branch} > /dev/null 2>&1")
141
+ end
142
+ end
143
+ end
144
+
145
+ puts 'Recloned successfully.'.green
146
+ 'Recloned successfully.'.green
147
+ else
148
+ # clone failed
149
+ puts 'Clone failed.'.red
150
+ nil
151
+ end
152
+ ensure
153
+ # always clean up temp directory
154
+ FileUtils.rm_rf(temp_dir)
155
+ end
156
+ end
157
+ end
158
+
159
+ GitReclone::HELP = <<~HELP.freeze
160
+ #{'git reclone'.red}: a git repo restoring tool
161
+
162
+ replaces your local copy with a fresh clone from the remote.
163
+ clones to a temp directory first, so your local copy is safe if the clone fails.
164
+ to restore from a particular remote repository, specify the host:
165
+
166
+ git reclone github # reclone using github
167
+ git reclone bitbucket # reclone using bitbucket
168
+ git reclone gitea # reclone using gitea
169
+ git reclone gogs # reclone using gogs
170
+ HELP
data/readme.md CHANGED
@@ -1,21 +1,19 @@
1
- git-reclone :rocket:
2
- =================
3
-
1
+ # git-reclone :rocket:
4
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/git-reclone.svg)](https://badge.fury.io/rb/git-reclone)
4
+ [![CI](https://github.com/jeremywrnr/git-reclone/actions/workflows/ci.yml/badge.svg)](https://github.com/jeremywrnr/git-reclone/actions/workflows/ci.yml)
5
5
  [![MIT](https://img.shields.io/npm/l/alt.svg?style=flat)](http://jeremywrnr.com/mit-license)
6
- -[![Gem Version](https://badge.fury.io/rb/git-reclone.svg)](https://badge.fury.io/rb/git-reclone)
7
- [![Build Status](https://travis-ci.org/jeremywrnr/git-reclone.svg?branch=master)](https://travis-ci.org/jeremywrnr/git-reclone)
8
- [![Code Climate](https://codeclimate.com/github/jeremywrnr/git-reclone/badges/gpa.svg)](https://codeclimate.com/github/jeremywrnr/git-reclone)
9
-
10
6
 
11
- destroy your local copy of a git repo, and reclone it from your remote.
7
+ replace your local copy of a git repo with a fresh clone from your remote.
12
8
 
13
- ![Screencast](http://i.imgur.com/HIvZCJB.gif)
9
+ ![Screencast](assets/screencast.gif)
14
10
 
15
11
  tested and works well for:
16
12
 
17
13
  - github
18
14
  - bitbucket
15
+ - gitea
16
+ - gogs
19
17
 
20
18
  ## setup
21
19
 
@@ -35,21 +33,27 @@ part (or all) of the host name. for example:
35
33
  git reclone bucket
36
34
  git reclone bitbucket
37
35
 
38
- will all overwrite the current repository with bitbucket's remote (assuming
39
- that some other host/repo name doesn't also match 'bitbucket').
36
+ will all replace the current repository with a fresh clone from bitbucket's
37
+ remote (assuming that some other host/repo name doesn't also match 'bitbucket').
38
+
39
+ The tool safely clones to a temporary directory first, so if the clone fails,
40
+ your local copy remains intact. Your current branch is automatically restored
41
+ after recloning (if it exists on the remote).
40
42
 
41
43
 
42
44
  ## about
43
45
 
44
46
  sometimes i mess up git histories, with (merges or rebasing, etc), and it
45
47
  becomes more of a headache to figure out how to undo what i did than to just
46
- reclone the remote copy and apply the changes i want in the right way. i was
47
- doing this often enough that i figured it would be nice to have a tool that
48
- just did this automatically. besides, it can be satisfying to just reclone your
49
- local copy and start anew - after all, what are backups meant for?
48
+ get a fresh clone from the remote and apply the changes i want in the right
49
+ way. i was doing this often enough that i figured it would be nice to have a
50
+ tool that just did this automatically. the tool clones to a temporary directory
51
+ first, so if something goes wrong, your local copy is safe. besides, it can be
52
+ satisfying to just start fresh from the remote - after all, what are backups
53
+ meant for?
50
54
 
51
55
  ## testing
52
56
 
53
57
  bundle || gem install bundler && bundle
54
- rake # running git-reclone's tests
58
+ just spec # running git-reclone's tests
55
59
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-reclone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Warner
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-11-15 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: colored
@@ -31,63 +30,51 @@ dependencies:
31
30
  - !ruby/object:Gem::Version
32
31
  version: '1.2'
33
32
  - !ruby/object:Gem::Dependency
34
- name: ronn
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '0'
40
- type: :development
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: '0'
47
- - !ruby/object:Gem::Dependency
48
- name: rake
33
+ name: rspec
49
34
  requirement: !ruby/object:Gem::Requirement
50
35
  requirements:
51
- - - ">="
36
+ - - "~>"
52
37
  - !ruby/object:Gem::Version
53
- version: '0'
38
+ version: '3.0'
54
39
  type: :development
55
40
  prerelease: false
56
41
  version_requirements: !ruby/object:Gem::Requirement
57
42
  requirements:
58
- - - ">="
43
+ - - "~>"
59
44
  - !ruby/object:Gem::Version
60
- version: '0'
45
+ version: '3.0'
61
46
  - !ruby/object:Gem::Dependency
62
- name: rspec
47
+ name: simplecov
63
48
  requirement: !ruby/object:Gem::Requirement
64
49
  requirements:
65
- - - ">="
50
+ - - "~>"
66
51
  - !ruby/object:Gem::Version
67
- version: '0'
52
+ version: 0.22.0
68
53
  type: :development
69
54
  prerelease: false
70
55
  version_requirements: !ruby/object:Gem::Requirement
71
56
  requirements:
72
- - - ">="
57
+ - - "~>"
73
58
  - !ruby/object:Gem::Version
74
- version: '0'
75
- description: reclone a local git repo from the remote.
59
+ version: 0.22.0
60
+ description: A tool to safely replace your local git repository with a fresh clone
61
+ from the remote. Clones to a temporary directory first to protect your local copy
62
+ if something goes wrong, and automatically restores your current branch.
76
63
  email: jeremy.warner@berkeley.edu
77
64
  executables:
78
65
  - git-reclone
79
66
  extensions: []
80
67
  extra_rdoc_files: []
81
68
  files:
69
+ - CHANGELOG.md
82
70
  - bin/git-reclone
83
- - lib/git-reclone-version.rb
84
- - lib/git-reclone.rb
71
+ - lib/git_reclone.rb
72
+ - lib/git_reclone/version.rb
85
73
  - readme.md
86
74
  homepage: http://github.com/jeremywrnr/git-reclone
87
75
  licenses:
88
76
  - MIT
89
77
  metadata: {}
90
- post_install_message:
91
78
  rdoc_options: []
92
79
  require_paths:
93
80
  - lib
@@ -95,15 +82,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
82
  requirements:
96
83
  - - ">="
97
84
  - !ruby/object:Gem::Version
98
- version: '0'
85
+ version: '3.1'
99
86
  required_rubygems_version: !ruby/object:Gem::Requirement
100
87
  requirements:
101
88
  - - ">="
102
89
  - !ruby/object:Gem::Version
103
90
  version: '0'
104
91
  requirements: []
105
- rubygems_version: 3.0.6
106
- signing_key:
92
+ rubygems_version: 4.0.10
107
93
  specification_version: 4
108
- summary: reclone a local git repo from the remote.
94
+ summary: Replace your local git repo with a fresh clone from the remote
109
95
  test_files: []
data/lib/git-reclone.rb DELETED
@@ -1,129 +0,0 @@
1
- # git-reclone gem
2
- # jeremy warner
3
-
4
- =begin
5
- todo: add an option to automatically add a backup of the local copy
6
- todo: add all remotes other than the origins, maintain connections
7
- todo: -b / --backup, and this actually should be the default (maybe)
8
- =end
9
-
10
- require "colored"
11
- require "fileutils"
12
- require "git-reclone-version"
13
-
14
- class GitReclone
15
- def initialize(test=false)
16
- @pdelay = 0.01 # constant for arrow speed
17
- @testing = test
18
- @verify = !test
19
- end
20
-
21
- def fire(args = [])
22
- opts = args.select {|a| a[0] == "-" }
23
- opts.each {|o| parse_opt o }
24
- exit 0 if (@testing || opts.first)
25
- parse_arg((args - opts).first)
26
- end
27
-
28
- def pexit(msg)
29
- puts msg
30
- exit 1
31
- end
32
-
33
- def parse_opt(o)
34
- case o
35
- when "--force", "-f"
36
- @verify = false
37
- when "--help", "-h"
38
- puts GitReclone::Help
39
- when "--version", "-v"
40
- puts GitReclone::Version
41
- end
42
- end
43
-
44
- def parse_arg(a)
45
- a.nil?? verify(remote) : verify(remote(a))
46
- end
47
-
48
- def no_repo?
49
- `git status 2>&1`.split("\n").first ==
50
- "fatal: Not a git repository (or any of the parent directories): .git"
51
- end
52
-
53
- def git_root
54
- %x{git rev-parse --show-toplevel}
55
- end
56
-
57
- def remotes
58
- %x{git remote -v}.split("\n").map { |r| r.split[1] }.uniq
59
- end
60
-
61
- def reclonebanner
62
- 25.times { |x| slowp "\rpreparing| ".red << "~" * x << "#==>".red }
63
- 25.times { |x| slowp "\rpreparing| ".red << " " * x << "~" * (25 - x) << "#==>".yellow }
64
- printf "\rREADY.".red << " " * 50 << "\n"
65
- end
66
-
67
- def slowp(x)
68
- sleep @pdelay
69
- printf x
70
- end
71
-
72
- # trying to parse out which remote should be the new source
73
- def remote(search = /.*/)
74
- pexit "Not currently in a git repository.".yellow if no_repo?
75
-
76
- r = remotes.find { |gr| gr.match search }
77
-
78
- pexit "No remotes found in this repository.".yellow if remotes.nil?
79
-
80
- if r.nil?
81
- errmsg = "No remotes found that match #{search.to_s.red}. All remotes:\n" + remotes.join("\n")
82
- pexit errmsg
83
- return errmsg
84
- else
85
- return r
86
- end
87
- end
88
-
89
- # show remote to user and confirm location (unless using -f)
90
- def verify(r)
91
- reclonebanner
92
- puts "Remote source:\t".red << r
93
- puts "Local target:\t".red << git_root
94
-
95
- if @verify
96
- puts "Warning: this will completely overwrite the local copy.".yellow
97
- printf "Continue recloning local repo? [yN] ".yellow
98
- unless $stdin.gets.chomp.downcase[0] == "y"
99
- puts "Reclone aborted.".green
100
- return
101
- end
102
- end
103
-
104
- reclone remote, git_root.chomp unless @testing
105
- end
106
-
107
- # overwrite the local copy of the repository with the remote one
108
- def reclone(remote, root)
109
- # remove the git repo from this computer
110
- if !@testing
111
- tree = Dir.glob("*", File::FNM_DOTMATCH).select {|d| not ['.','..'].include? d }
112
- FileUtils.rmtree (tree)
113
- end
114
-
115
- cloner = "git clone \"#{remote}\" \"#{root}\""
116
-
117
- puts "Recloned successfully.".green if system(cloner)
118
- end
119
- end
120
-
121
- GitReclone::Help = <<-HELP
122
- #{'git reclone'.red}: a git repo restoring tool
123
-
124
- reclones from the remote listed first, overwriting your local copy.
125
- to restore from a particular remote repository, specify the host:
126
-
127
- git reclone bitbucket # reclone using bitbucket
128
- git reclone github # reclone using github
129
- HELP