gitti 0.2.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23b94ce3c7dbeb1eb816fc266a520ff277a74a06
4
- data.tar.gz: dff2e5ff8d5d961ae46cc4da765d75a1dfb6f92e
3
+ metadata.gz: 651f519f3b5f3ecf8a13a5125554cac2d69790f6
4
+ data.tar.gz: 7ae7285e8ac625336869c7d4de1d078c11c5ee6d
5
5
  SHA512:
6
- metadata.gz: 740f8d8ca2e1f4e24c97458e3a47e947727613a12649c18d39d7ced494cb73d3c01a5cd64b682ea01563d4eff989d40789cee16441e68cac24b0bd006c6b2f03
7
- data.tar.gz: 1066b7918f78d9ea829e1a53fd9865df7cb3dc9a9a20b5085c2d05a1b1a1ba64b5dbb722f00bb40d104b1cae64aa62370a0171378e409d5818ccaf1fa816a344
6
+ metadata.gz: 7c002bac4f5622a3083b27fa2e29d69736821d14c7b521ecd1a00b06cd62d80cae762e853e96943baa242e77568043a356fecc8c036c8856f18c8eac42facf0c
7
+ data.tar.gz: 694934d8ea8263d11b90f7a14a01f8f59d3d71a695b728ebd82927e66d554cf1e59195199af7c960e930cc9cb4d9ad4c3d93abec28df9fe1aca931304e1f4698
File without changes
@@ -1,8 +1,13 @@
1
- HISTORY.md
1
+ CHANGELOG.md
2
2
  Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/gitti.rb
6
- lib/gitti/lib.rb
7
- lib/gitti/support/reposet.rb
6
+ lib/gitti/base.rb
7
+ lib/gitti/git.rb
8
+ lib/gitti/mirror.rb
9
+ lib/gitti/project.rb
10
+ lib/gitti/reposet.rb
8
11
  lib/gitti/version.rb
12
+ test/helper.rb
13
+ test/test_base.rb
data/README.md CHANGED
@@ -1,16 +1,162 @@
1
1
  # gitti
2
2
 
3
- gitti gem - (yet) another (lite) git command line wrapper / library
3
+ gitti gem - (yet) another (lite) git command line helper / wrapper
4
4
 
5
- * home :: [github.com/rubylibs/gitti](https://github.com/rubylibs/gitti)
6
- * bugs :: [github.com/rubylibs/gitti/issues](https://github.com/rubylibs/gitti/issues)
5
+ * home :: [github.com/rubycoco/gitti](https://github.com/rubycoco/gitti)
6
+ * bugs :: [github.com/rubycoco/gitti/issues](https://github.com/rubycoco/gitti/issues)
7
7
  * gem :: [rubygems.org/gems/gitti](https://rubygems.org/gems/gitti)
8
8
  * rdoc :: [rubydoc.info/gems/gitti](http://rubydoc.info/gems/gitti)
9
9
 
10
10
 
11
+
11
12
  ## Usage
12
13
 
13
- TBD
14
+ `Git` • `GitProject` • `GitMirror`
15
+
16
+
17
+ ### `Git` Class
18
+
19
+ Use the `Git` class for "low-level / to the metal" git commands
20
+ that run in your current working directory.
21
+ Example:
22
+
23
+ ``` ruby
24
+
25
+ ###############
26
+ ## "setup" starter git commands
27
+
28
+ Git.clone( "https://github.com/rubycoco/gitti.git" )
29
+ Git.clone( "https://github.com/rubycoco/gitti.git", "gitti-clone" )
30
+ # -or- -- if you have write / commit access use ssh
31
+ Git.clone( "git@github.com:rubycoco/gitti.git" )
32
+ Git.clone( "git@github.com:rubycoco/gitti.git", "gitti-clone" )
33
+
34
+ Git.mirror( "https://github.com/rubycoco/gitti.git" ) ## same as git clone --mirror
35
+
36
+ #################
37
+ ## standard git commands
38
+
39
+ Git.version ## same as git --version
40
+ Git.status
41
+ Git.status( short: true ) ## same as Git.changes
42
+ Git.changes ## same as git status --short
43
+
44
+ #####################
45
+ ## status helpers
46
+
47
+ Git.clean?
48
+ Git.changes?
49
+ Git.dirty? ## alias for changes?
50
+
51
+ #######
52
+ ## more (major) git commands
53
+
54
+ Git.fetch
55
+ Git.pull
56
+ Git.fast_forward ## same as git pull --ff-only
57
+ Git.ff ## alias for fast_forward
58
+ Git.push
59
+ Git.add( "pathspec" )
60
+ Git.add_all ## same as git --all
61
+ Git.commit( "message" )
62
+
63
+ Git.files ## same as git ls-tree --full-tree --name-only -r HEAD
64
+
65
+ Git.check ## same as git fsck
66
+ Git.fsck ## alias for check
67
+ Git.checksum ## another alias for check
68
+
69
+ Git.master? ## on master branch
70
+ Git.main? ## on main branch
71
+
72
+ Git.origin ## same as git remote show origin
73
+ Git.upstream ## same as git remote show upstream
74
+ Git.origin?
75
+ Git.upstream?
76
+
77
+ Git.config( "user.name" ) ## use --get option
78
+ Git.config( "user.name", show_origin: true ) ## add --show-origin flag
79
+ Git.config( "user.name", show_scope: true ) ## add --show-scope flag
80
+
81
+ Git.config( /user/ ) ## use --get-regexp option
82
+ Git.config( /user/, show_origin: true ) ## add --show-origin flag
83
+ Git.config( /user/, show_scope: true ) ## add --show-scope flag
84
+ ```
85
+
86
+
87
+
88
+ ### `GitProject` Class
89
+
90
+ Use the `GitProject` class for existing git repo(sitories)
91
+ with workspace. Example:
92
+
93
+ ``` ruby
94
+ GitProject.open( "rubycoco/gitti" ) do |proj|
95
+ proj.status
96
+ proj.status( short: true )
97
+ proj.changes
98
+ proj.clean?
99
+ proj.changes?
100
+ proj.dirty?
101
+
102
+ proj.fetch
103
+ proj.pull
104
+ proj.fast_forward
105
+ proj.ff
106
+
107
+ proj.push
108
+
109
+ proj.add( "pathspec" )
110
+ proj.add_all
111
+ proj.commit( "message" )
112
+
113
+ proj.files
114
+
115
+ proj.master?
116
+ proj.main?
117
+
118
+ proj.origin
119
+ proj.upstream
120
+ proj.origin?
121
+ proj.upstream?
122
+ end
123
+ ```
124
+
125
+
126
+ ### `GitMirror` Class
127
+
128
+ Use the `GitMirror` class for existing mirrored (bare) git repo(sitories)
129
+ without workspace. Example:
130
+
131
+ ``` ruby
132
+ GitMirror.open( "rubycoco/gitti.git" ) do |mirror|
133
+ mirror.update # sames as git remote update
134
+ end
135
+ ```
136
+
137
+
138
+
139
+ That's it for now.
140
+
141
+
142
+
143
+ ## Real World Usage
144
+
145
+ The [`monos`](https://github.com/rubycoco/monos) gem incl. some monorepo / mono source tree tools and (startup) scripts
146
+ that let you run git commands on multiple repos.
147
+
148
+
149
+
150
+ ## Installation
151
+
152
+ Use
153
+
154
+ gem install gitti
155
+
156
+ or add to your Gemfile
157
+
158
+ gem 'gitti'
159
+
14
160
 
15
161
 
16
162
  ## License
data/Rakefile CHANGED
@@ -3,28 +3,26 @@ require './lib/gitti/version.rb'
3
3
 
4
4
  Hoe.spec 'gitti' do
5
5
 
6
- self.version = Gitti::VERSION
6
+ self.version = GittiCore::VERSION
7
7
 
8
- self.summary = 'gitti - (yet) another (lite) git command line wrapper / library'
8
+ self.summary = 'gitti - (yet) another (lite) git command line helper / wrapper'
9
9
  self.description = summary
10
10
 
11
- self.urls = ['https://github.com/rubylibs/gitti']
11
+ self.urls = { home: 'https://github.com/rubycoco/gitti' }
12
12
 
13
13
  self.author = 'Gerald Bauer'
14
14
  self.email = 'ruby-talk@ruby-lang.org'
15
15
 
16
16
  # switch extension to .markdown for gihub formatting
17
17
  self.readme_file = 'README.md'
18
- self.history_file = 'HISTORY.md'
18
+ self.history_file = 'CHANGELOG.md'
19
19
 
20
- self.extra_deps = [
21
- ['logutils' ],
22
- ]
20
+ self.extra_deps = []
23
21
 
24
22
  self.licenses = ['Public Domain']
25
23
 
26
24
  self.spec_extras = {
27
- required_ruby_version: '>= 1.9.2'
25
+ required_ruby_version: '>= 2.2.2'
28
26
  }
29
27
 
30
28
  end
@@ -1,24 +1,7 @@
1
- # encoding: utf-8
1
+ require_relative 'gitti/base'
2
2
 
3
- require 'net/http'
4
- require "net/https"
5
- require 'uri'
3
+ ## note: auto include Gitti; for "modular" version use ("Sinatra-style")
4
+ ## require "gitti/base"
6
5
 
7
- require 'pp'
8
- require 'json'
9
- require 'yaml'
6
+ include Gitti
10
7
 
11
-
12
- # 3rd party gems/libs
13
- require 'logutils'
14
-
15
- # our own code
16
- require 'gitti/version' # note: let version always go first
17
- require 'gitti/lib'
18
-
19
- ## todo/check: move to its own gem e.g. gitti-support later - why? why not??
20
- require 'gitti/support/reposet'
21
-
22
-
23
- # say hello
24
- puts Gitti.banner if defined?($RUBYLIBS_DEBUG)
@@ -0,0 +1,57 @@
1
+ require 'pp'
2
+ require 'time'
3
+ require 'date' ## e.g. Date.today etc.
4
+ require 'yaml'
5
+ require 'json'
6
+ require 'uri'
7
+ require 'net/http'
8
+ require "net/https"
9
+ require 'open3'
10
+ require 'fileutils' ## e.g. FileUtils.mkdir_p etc.
11
+
12
+
13
+
14
+ # our own code
15
+ require 'gitti/version' # note: let version always go first
16
+ require 'gitti/git'
17
+ require 'gitti/project'
18
+ require 'gitti/mirror'
19
+ require 'gitti/reposet'
20
+
21
+
22
+
23
+ module Gitti
24
+ ## todo: change to GitHubRepoRef or GitHubProject
25
+ ## or Git::GitHub or Git::Source::GitHub or such - why? why not?
26
+ class GitHubRepo
27
+ attr_reader :owner, :name
28
+
29
+ def initialize( owner, name )
30
+ @owner = owner ## use/rename to login or something - why? why not??
31
+ @name = name # e.g. "rubylibs/webservice"
32
+ end
33
+
34
+
35
+ def ssh_clone_url
36
+ ## check: use https: as default? for github - http:// still supported? or redirected?
37
+ ## "http://github.com/#{@owner}/#{@name}"
38
+ "git@github.com:#{@owner}/#{@name}.git"
39
+ end
40
+
41
+ def http_clone_url ## use clone_url( http: true ) -- why? why not?
42
+ ## note: https is default for github - http:// gets redirected to https://
43
+ "http://github.com/#{@owner}/#{@name}"
44
+ end
45
+
46
+ def https_clone_url
47
+ "https://github.com/#{@owner}/#{@name}"
48
+ end
49
+
50
+
51
+ end ## class GitHubRepo
52
+ end ## module Gitti
53
+
54
+
55
+
56
+ # say hello
57
+ puts GittiCore.banner ## if defined?( $RUBYCOCO_DEBUG )
@@ -0,0 +1,316 @@
1
+ module Gitti
2
+
3
+ ## raised by Git::Shell.run -- check if top-level ShellError alread exists?
4
+ ## use ShellError or RunError - why? why not?
5
+ ## and make Git::Shell top-level e.g. Shell - why? why not?
6
+ class GitError < StandardError
7
+ end
8
+
9
+
10
+ class Git ## make Git a module - why? why not?
11
+
12
+ ###
13
+ ## todo/fix: change opts=nil to *args or such - why? why not?
14
+
15
+
16
+ ###############
17
+ ## "setup" starter git commands
18
+
19
+ def self.clone( repo, name=nil, depth: nil )
20
+ cmd = "git clone"
21
+ cmd << " --depth #{depth}" unless depth.nil?
22
+ cmd << " #{repo}"
23
+ cmd << " #{name}" unless name.nil? || name.empty?
24
+ Shell.run( cmd )
25
+ end
26
+
27
+ ###
28
+ ## What's the difference between git clone --mirror and git clone --bare
29
+ ## see https://stackoverflow.com/questions/3959924/whats-the-difference-between-git-clone-mirror-and-git-clone-bare
30
+ ##
31
+ ## The git clone help page has this to say about --mirror:
32
+ ## > Set up a mirror of the remote repository. This implies --bare
33
+ ##
34
+ ## The difference is that when using --mirror, all refs are copied as-is.
35
+ ## This means everything: remote-tracking branches, notes, refs/originals/*
36
+ ## (backups from filter-branch). The cloned repo has it all.
37
+ ## It's also set up so that a remote update will re-fetch everything from the origin
38
+ ## (overwriting the copied refs). The idea is really to mirror the repository,
39
+ ## to have a total copy, so that you could for example host your central repo
40
+ ## in multiple places, or back it up. Think of just straight-up copying the repo,
41
+ ## except in a much more elegant git way.
42
+ ##
43
+ ## The new documentation pretty much says all this:
44
+ ## see https://git-scm.com/docs/git-clone
45
+ ##
46
+ ## --mirror
47
+ ## Set up a mirror of the source repository. This implies --bare.
48
+ ## Compared to --bare, --mirror not only maps local branches of the source
49
+ ## to local branches of the target, it maps all refs
50
+ ## (including remote-tracking branches, notes etc.) and sets up a refspec configuration
51
+ ## such that all these refs are overwritten by a git remote update
52
+ ## in the target repository.
53
+ ##
54
+ ## More Articles / Resources:
55
+ ## https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/duplicating-a-repository
56
+
57
+
58
+ ## add -n (--no-checkout) -- needed - why? why not?
59
+ ## add --no-hardlinks -- needed/recommended - why? why not?
60
+
61
+ def self.mirror( repo )
62
+ cmd = "git clone --mirror #{repo}"
63
+ Shell.run( cmd )
64
+ end
65
+
66
+
67
+ #################
68
+ ## standard git commands
69
+
70
+ def self.version
71
+ cmd = 'git --version'
72
+ Shell.run( cmd )
73
+ end
74
+
75
+ def self.status( short: false )
76
+ cmd = 'git status'
77
+ cmd << " --short" if short
78
+ Shell.run( cmd )
79
+ end
80
+
81
+ def self.changes ## same as git status --short - keep shortcut / alias - why? why not?
82
+ ## returns changed files - one per line or empty if no changes
83
+ cmd = 'git status --short'
84
+ Shell.run( cmd )
85
+ end
86
+
87
+ #####################
88
+ ## status helpers
89
+
90
+ ## git status --short returns empty stdout/list
91
+ def self.clean?() changes.empty?; end
92
+
93
+ def self.changes?() clean? == false; end ## reverse of clean?
94
+ class << self
95
+ alias_method :dirty?, :changes? ## add alias
96
+ end
97
+
98
+
99
+ #######
100
+ ## more (major) git commands
101
+
102
+ def self.fetch
103
+ cmd = 'git fetch'
104
+ Shell.run( cmd )
105
+ end
106
+
107
+ def self.pull
108
+ cmd = 'git pull'
109
+ Shell.run( cmd )
110
+ end
111
+
112
+ def self.fast_forward
113
+ cmd = 'git pull --ff-only'
114
+ Shell.run( cmd )
115
+ end
116
+ class << self
117
+ alias_method :ff, :fast_forward ## add alias
118
+ end
119
+
120
+
121
+ def self.push
122
+ cmd = 'git push'
123
+ Shell.run( cmd )
124
+ end
125
+
126
+ def self.add( *pathspecs ) ## e.g. git add . or git add *.rb or such
127
+ cmd = 'git add'
128
+ pathspecs = ['.'] if pathspecs.size == 0
129
+ cmd << " #{pathspecs.join('')}"
130
+ Shell.run( cmd )
131
+ end
132
+
133
+ def self.add_all
134
+ cmd = 'git add --all'
135
+ Shell.run( cmd )
136
+ end
137
+
138
+ def self.commit( message )
139
+ ### todo/check: make message.nil? an ArgumentError - why? why not?
140
+ ### if message.nil? || message.empty?
141
+
142
+ cmd = 'git commit'
143
+ cmd << %Q{ -m "#{message}"}
144
+
145
+ Shell.run( cmd )
146
+ end
147
+
148
+
149
+ #############
150
+ # change git ls-files to git ls-tree ... - why? why not?
151
+ ## - note: git ls-files will include stages files too
152
+ # not only committed ones!!!
153
+ #
154
+ # git ls-tree --full-tree --name-only -r HEAD
155
+ # 1) --full-tree makes the command run as if you were in the repo's root directory.
156
+ # 2) -r recurses into subdirectories. Combined with --full-tree, this gives you all committed, tracked files.
157
+ # 3) --name-only removes SHA / permission info for when you just want the file paths.
158
+ # 4) HEAD specifies which branch you want the list of tracked, committed files for.
159
+ # You could change this to master or any other branch name, but HEAD is the commit you have checked out right now.
160
+ #
161
+ # see https://stackoverflow.com/questions/15606955/how-can-i-make-git-show-a-list-of-the-files-that-are-being-tracked
162
+ #
163
+ # was:
164
+
165
+ def self.files ## was: e.g. git ls-files . or git ls-files *.rb or such
166
+ ### todo/check: include --full-tree - why? why not?
167
+ ## will ALWAYS list all files NOT depending on (current) working directory
168
+
169
+ cmd = 'git ls-tree --full-tree --name-only -r HEAD' # was: 'git ls-files'
170
+ Shell.run( cmd )
171
+ end
172
+ ## add list_files or ls_files alias - why? why not?
173
+
174
+
175
+ ########
176
+ ## query git configuration helpers
177
+ def self.config( prop,
178
+ show_origin: false,
179
+ show_scope: false ) ## find a better name e.g. config_get? why? why not?
180
+ cmd = "git config"
181
+ cmd << " --show-origin" if show_origin
182
+ cmd << " --show-scope" if show_scope
183
+
184
+ if prop.is_a?( Regexp )
185
+ ## note: use Regexp#source
186
+ ## Returns the original string of the pattern.
187
+ ## e.g. /ab+c/ix.source #=> "ab+c"
188
+ ## Note that escape sequences are retained as is.
189
+ ## /\x20\+/.source #=> "\\x20\\+"
190
+ cmd << " --get-regexp #{prop.source}"
191
+ else ## assume string
192
+ cmd << " --get #{prop}"
193
+ end
194
+
195
+ Shell.run( cmd )
196
+ end
197
+
198
+
199
+ def self.branch
200
+ cmd = 'git branch'
201
+ Shell.run( cmd )
202
+ end
203
+
204
+ def self.master?
205
+ output = branch ## check for '* master'
206
+ output.split( /\r?\n/ ).include?( '* master' )
207
+ end
208
+
209
+ def self.main?
210
+ output = branch ## check for '* main'
211
+ output.split( /\r?\n/ ).include?('* main')
212
+ end
213
+
214
+ ## git remote update will update all of your branches
215
+ ## set to track remote ones, but not merge any changes in.
216
+ ##
217
+ ## git fetch --all didn't exist at one time, so git remote update what more useful.
218
+ ## Now that --all has been added to git fetch, git remote update is not really necessary.
219
+ ##
220
+ ## Differences between git remote update and fetch?
221
+ ## Is git remote update the equivalent of git fetch?
222
+ ## see https://stackoverflow.com/questions/1856499/differences-between-git-remote-update-and-fetch/17512004#17512004
223
+ ##
224
+ ## git fetch learned --all and --multiple options,
225
+ ## to run fetch from many repositories,
226
+ ## and --prune option to remove remote tracking branches that went stale.
227
+ ## These make git remote update and git remote prune less necessary
228
+ ## (there is no plan to remove remote update nor remote prune, though).
229
+ def self.update
230
+ cmd = 'git remote update'
231
+ Shell.run( cmd )
232
+ end
233
+
234
+
235
+ def self.origin ## e.g. git remote show origin
236
+ cmd = "git remote show origin"
237
+ Shell.run( cmd )
238
+ end
239
+
240
+ def self.upstream ## e.g. git remote show origin
241
+ cmd = "git remote show upstream"
242
+ Shell.run( cmd )
243
+ end
244
+
245
+ def self.remote
246
+ cmd = "git remote"
247
+ Shell.run( cmd )
248
+ end
249
+
250
+ def self.origin?
251
+ output = remote ## check for 'origin'
252
+ output.split( /\r?\n/ ).include?( 'origin' )
253
+ end
254
+
255
+ def self.upstream?
256
+ output = remote ## check for 'upstream'
257
+ output.split( /\r?\n/ ).include?( 'upstream' )
258
+ end
259
+
260
+
261
+
262
+ def self.check ## e.g. git fsck - check/validate hash of objects
263
+ cmd = "git fsck"
264
+ Shell.run( cmd )
265
+ end
266
+ class << self
267
+ alias_method :fsck, :check ## add alias
268
+ alias_method :checksum, :check
269
+ end
270
+
271
+
272
+
273
+ ###
274
+ # use nested class for "base" for running commands - why? why not?
275
+ class Shell
276
+ def self.run( cmd )
277
+ print "cmd exec >#{cmd}<..."
278
+ stdout, stderr, status = Open3.capture3( cmd )
279
+
280
+ if status.success?
281
+ print " OK"
282
+ print "\n"
283
+ else
284
+ print " FAIL (#{status.exitstatus})"
285
+ print "\n"
286
+ end
287
+
288
+ unless stdout.empty?
289
+ puts stdout
290
+ end
291
+
292
+ unless stderr.empty?
293
+ ## todo/check: or use >2: or &2: or such
294
+ ## stderr output not always an error (that is, exit status might be 0)
295
+ puts "2>"
296
+ puts stderr
297
+ end
298
+
299
+ if status.success?
300
+ stdout # return stdout string
301
+ else
302
+ puts "!! ERROR: cmd exec >#{cmd}< failed with exit status #{status.exitstatus}:"
303
+ puts stderr
304
+
305
+ ### todo/fix: do NOT use GitError here!!! make it more "general"
306
+ ### use a Git::Shell.run() wrapper or such - why? why not?
307
+ ## or use a Shell.git() or Shell.git_run() ???
308
+ ## or pass in error class - why? why not?
309
+ raise GitError, "cmd exec >#{cmd}< failed with exit status #{status.exitstatus}<: #{stderr}"
310
+ end
311
+ end
312
+ end # class Git::Shell
313
+
314
+ end # class Git
315
+
316
+ end # module Gitti
@@ -0,0 +1,33 @@
1
+ module Gitti
2
+
3
+ class GitMirror
4
+ def self.open( path, &blk )
5
+ new( path ).open( &blk )
6
+ end
7
+
8
+ def self.update( path ) ### all-in-one convenience shortcut
9
+ new( path).open { |mirror| mirror.update }
10
+ end
11
+
12
+
13
+
14
+ def initialize( path )
15
+ raise ArgumentError, "dir >#{path}< not found; dir MUST already exist for GitMirror class - sorry" unless Dir.exist?( path )
16
+ ## todo/check: check for more dirs and files e.g.
17
+ ## /info,/objects,/refs, /hooks, HEAD, config, description -- why? why not?
18
+ raise ArgumentError, "dir >#{path}/objects< not found; dir MUST already be initialized with git for GitMirror class - sorry" unless Dir.exist?( "#{path}/objects" )
19
+ @path = path
20
+ end
21
+
22
+
23
+ def open( &blk )
24
+ Dir.chdir( @path ) do
25
+ blk.call( self )
26
+ end
27
+ end
28
+
29
+ def update() Git.update; end
30
+
31
+ end # class GitMirror
32
+ end # module Gitti
33
+
@@ -0,0 +1,61 @@
1
+ module Gitti
2
+
3
+ class GitProject
4
+ def self.open( path, &blk )
5
+ new( path ).open( &blk )
6
+ end
7
+
8
+ def initialize( path )
9
+ raise ArgumentError, "dir >#{path}< not found; dir MUST already exist for GitProject class - sorry" unless Dir.exist?( path )
10
+ raise ArgumentError, "dir >#{path}/.git< not found; dir MUST already be initialized with git for GitProject class - sorry" unless Dir.exist?( "#{path}/.git" )
11
+ @path = path
12
+ end
13
+
14
+
15
+ def open( &blk )
16
+ ## puts "Dir.getwd: #{Dir.getwd}"
17
+ Dir.chdir( @path ) do
18
+ blk.call( self )
19
+ end
20
+ ## puts "Dir.getwd: #{Dir.getwd}"
21
+ end
22
+
23
+
24
+ def status( short: false ) Git.status( short: short ); end
25
+ def changes() Git.changes; end
26
+ def clean?() Git.clean?; end
27
+ def changes?() Git.changes?; end
28
+ alias_method :dirty?, :changes?
29
+
30
+
31
+ def fetch() Git.fetch; end
32
+ def pull() Git.pull; end
33
+ def fast_forward() Git.fast_forward; end
34
+ alias_method :ff, :fast_forward
35
+
36
+ def push() Git.push; end
37
+
38
+ def add( *pathspecs ) Git.add( *pathspecs ); end
39
+ def add_all() Git.add_all; end
40
+ def commit( message ) Git.commit( message ); end
41
+
42
+ def files() Git.files; end
43
+
44
+
45
+ ### remote show origin|upstream|etc.
46
+ def remote() Git.remote; end
47
+ def origin() Git.origin; end
48
+ def upstream() Git.upstream; end
49
+ def origin?() Git.origin?; end
50
+ def upstream?() Git.upstream?; end
51
+
52
+ ### branch management
53
+ def branch() Git.branch; end
54
+ def master?() Git.master?; end
55
+ def main?() Git.main?; end
56
+
57
+
58
+ def run( cmd ) Git::Shell.run( cmd ); end
59
+ end # class GitProject
60
+ end # module Gitti
61
+
@@ -0,0 +1,42 @@
1
+
2
+ module Gitti
3
+
4
+
5
+ class GitRepoSet ## todo: rename to Hash/Dict/List/Map or use GitHubRepoSet ??
6
+
7
+ def self.read( path )
8
+ txt = File.open( path, 'r:utf-8') { |f| f.read }
9
+ hash = YAML.load( txt )
10
+ new( hash )
11
+ end
12
+
13
+
14
+ def initialize( hash )
15
+ @hash = hash
16
+ end
17
+
18
+ def size
19
+ ## sum up total number of repos
20
+ @size ||= @hash.reduce(0) {|sum,(_,names)| sum+= names.size; sum }
21
+ end
22
+
23
+ def each
24
+ @hash.each do |org_with_counter,names|
25
+
26
+ ## remove optional number from key e.g.
27
+ ## mrhydescripts (3) => mrhydescripts
28
+ ## footballjs (4) => footballjs
29
+ ## etc.
30
+
31
+ org = org_with_counter.sub( /\([0-9]+\)/, '' ).strip
32
+
33
+ ## puts " -- #{key_with_counter} [#{key}] --"
34
+
35
+ yield( org, names )
36
+ end
37
+ end
38
+
39
+ end ## class GitRepoSet
40
+
41
+ end ## module Gitti
42
+
@@ -1,9 +1,14 @@
1
- # encoding: utf-8
2
1
 
3
- module Gitti
2
+ ### note: use a different module for version (meta) info
3
+ ### that is, GittiCore and NOT Gitti
4
+ ### why? do NOT "pollute" Gitti with MAJOR, MINOR, PATH, and
5
+ ### self.banner, self.root, etc.
6
+
7
+
8
+ module GittiCore ## todo/check: rename GittiBase or GittiMeta or such - why? why not?
4
9
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
5
- MINOR = 2
6
- PATCH = 0
10
+ MINOR = 4
11
+ PATCH = 2
7
12
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
13
 
9
14
  def self.version
@@ -17,5 +22,5 @@ module Gitti
17
22
  def self.root
18
23
  "#{File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )}"
19
24
  end
20
- end # module Gitti
25
+ end # module GittiCore
21
26
 
@@ -0,0 +1,7 @@
1
+ ## minitest setup
2
+ require 'minitest/autorun'
3
+
4
+
5
+ ## our own code
6
+ require 'gitti'
7
+
@@ -0,0 +1,43 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_base.rb
4
+
5
+ require 'helper'
6
+
7
+ class TestBase < MiniTest::Test
8
+
9
+ def test_branch
10
+ Git.branch
11
+ assert_equal true, Git.master?
12
+ assert_equal false, Git.main?
13
+
14
+ Git.remote
15
+ assert_equal true, Git.origin?
16
+ assert_equal false, Git.upstream?
17
+ end
18
+
19
+
20
+ def test_git_config
21
+ puts "---"
22
+ Git.config( 'user.name' )
23
+ Git.config( 'user.name', show_origin: true )
24
+ ## Git.config( 'user.name', show_scope: true )
25
+
26
+ puts "---"
27
+ Git.config( /user/ ) ## note: pass in regex for regex match/search
28
+ Git.config( /user/, show_origin: true )
29
+ ## Git.config( /user/, show_scope: true )
30
+
31
+ puts "---"
32
+ Git.config( /user\./ ) ## note: pass in regex for regex match/search
33
+
34
+ puts "---"
35
+ ## note: if NOT found Git.config will exit(1) !!!
36
+ ## Git.config( /proxy/, show_origin: true )
37
+ ## Git.config( /http/, show_origin: true )
38
+
39
+ puts "---"
40
+ end
41
+
42
+ end # class TestBase
43
+
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitti
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-22 00:00:00.000000000 Z
11
+ date: 2020-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: logutils
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
13
  - !ruby/object:Gem::Dependency
28
14
  name: rdoc
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -44,32 +30,37 @@ dependencies:
44
30
  requirements:
45
31
  - - "~>"
46
32
  - !ruby/object:Gem::Version
47
- version: '3.14'
33
+ version: '3.16'
48
34
  type: :development
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
38
  - - "~>"
53
39
  - !ruby/object:Gem::Version
54
- version: '3.14'
55
- description: gitti - (yet) another (lite) git command line wrapper / library
40
+ version: '3.16'
41
+ description: gitti - (yet) another (lite) git command line helper / wrapper
56
42
  email: ruby-talk@ruby-lang.org
57
43
  executables: []
58
44
  extensions: []
59
45
  extra_rdoc_files:
60
- - HISTORY.md
46
+ - CHANGELOG.md
61
47
  - Manifest.txt
62
48
  - README.md
63
49
  files:
64
- - HISTORY.md
50
+ - CHANGELOG.md
65
51
  - Manifest.txt
66
52
  - README.md
67
53
  - Rakefile
68
54
  - lib/gitti.rb
69
- - lib/gitti/lib.rb
70
- - lib/gitti/support/reposet.rb
55
+ - lib/gitti/base.rb
56
+ - lib/gitti/git.rb
57
+ - lib/gitti/mirror.rb
58
+ - lib/gitti/project.rb
59
+ - lib/gitti/reposet.rb
71
60
  - lib/gitti/version.rb
72
- homepage: https://github.com/rubylibs/gitti
61
+ - test/helper.rb
62
+ - test/test_base.rb
63
+ homepage: https://github.com/rubycoco/gitti
73
64
  licenses:
74
65
  - Public Domain
75
66
  metadata: {}
@@ -83,7 +74,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
83
74
  requirements:
84
75
  - - ">="
85
76
  - !ruby/object:Gem::Version
86
- version: 1.9.2
77
+ version: 2.2.2
87
78
  required_rubygems_version: !ruby/object:Gem::Requirement
88
79
  requirements:
89
80
  - - ">="
@@ -91,8 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
82
  version: '0'
92
83
  requirements: []
93
84
  rubyforge_project:
94
- rubygems_version: 2.2.3
85
+ rubygems_version: 2.5.2
95
86
  signing_key:
96
87
  specification_version: 4
97
- summary: gitti - (yet) another (lite) git command line wrapper / library
88
+ summary: gitti - (yet) another (lite) git command line helper / wrapper
98
89
  test_files: []
@@ -1,83 +0,0 @@
1
- # encoding: utf-8
2
-
3
-
4
- module Gitti
5
-
6
- class GitError < StandardError
7
- end
8
-
9
- class GitLib
10
-
11
- def clone( repo, opts={} )
12
- command( "clone #{repo}" )
13
- end
14
-
15
- def mirror( repo, opts={} )
16
- command( "clone --mirror #{repo}" )
17
- end
18
-
19
- def pull( opts={} )
20
- command( "pull" )
21
- end
22
-
23
- def remote_update( opts={} )
24
- command( "remote update" )
25
- end
26
-
27
-
28
- ## todo/fix:
29
- ## add last_exit or something ?? why? why not??
30
-
31
- def command( cmd )
32
- ## note: for now use Kernel#system for calling external git command
33
- ##
34
-
35
- cmdline = "git #{cmd}"
36
- puts " trying >#{cmdline}< in (#{Dir.pwd})..."
37
-
38
- result = nil
39
- result = system( cmdline )
40
-
41
- pp result
42
-
43
- # note: Kernel#system returns
44
- # - true if the command gives zero exit status
45
- # - false for non zero exit status
46
- # - nil if command execution fails
47
- # An error status is available in $?.
48
-
49
- if result.nil?
50
- puts "*** error was #{$?}"
51
- fail "[Kernel.system] command execution failed >#{cmdline}< - #{$?}"
52
- elsif result ## true => zero exit code (OK)
53
- puts 'OK' ## zero exit; assume OK
54
- true ## assume ok
55
- else ## false => non-zero exit code (ERR/NOK)
56
- puts "*** error: non-zero exit - #{$?} !!" ## non-zero exit (e.g. 1,2,3,etc.); assume error
57
-
58
- ## log error for now ???
59
- # File.open( './errors.log', 'a' ) do |f|
60
- # f.write "#{Time.now} -- repo #{@owner}/#{@name} - command execution failed - non-zero exit\n"
61
- # end
62
- raise GitError.new( "command execution failed >#{cmdline}< - non-zero exit (#{$?})" )
63
- end
64
- end # method command
65
- end # class Lib
66
-
67
-
68
- module Git
69
- ## todo/fix: use "shared" singelton lib - why? why not??
70
- def self.clone( repo, opts={} ) GitLib.new.clone( repo, opts ); end
71
- def self.mirror( repo, opts={} ) GitLib.new.mirror( repo, opts ); end
72
-
73
- def self.pull( opts={} ) GitLib.new.pull( opts ); end
74
- def self.remote_update( opts={} ) GitLib.new.remote_update( opts ); end
75
- end # module Git
76
-
77
- end # module Gitti
78
-
79
-
80
- ### convenience top level Git module - check if defined? make optional? why? why not??
81
- ## Git = Gitti::Git
82
-
83
- # for now use include Gitti - why? why not??
@@ -1,37 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Gitti
4
-
5
-
6
- class GitRepoSet ## todo: rename to Hash/Dict/List/Map or use GitHubRepoSet ??
7
-
8
- def self.from_file( path )
9
- hash = YAML.load_file( path )
10
- self.new( hash )
11
- end
12
-
13
-
14
- def initialize( hash )
15
- @hash = hash
16
- end
17
-
18
- def each
19
- @hash.each do |key_with_counter,values|
20
-
21
- ## remove optional number from key e.g.
22
- ## mrhydescripts (3) => mrhydescripts
23
- ## footballjs (4) => footballjs
24
- ## etc.
25
-
26
- key = key_with_counter.sub( /\s+\([0-9]+\)/, '' )
27
-
28
- puts " -- #{key_with_counter} [#{key}] --"
29
-
30
- yield( key, values )
31
- end
32
- end
33
-
34
- end ## class GitRepoSet
35
-
36
- end ## module Gitti
37
-