snowblink-github 0.3.4

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.
@@ -0,0 +1,113 @@
1
+ desc "Project network tools - sub-commands : web [user], list, fetch, commits"
2
+ flags :after => "Only show commits after a certain date"
3
+ flags :before => "Only show commits before a certain date"
4
+ flags :shas => "Only show shas"
5
+ flags :project => "Filter commits on a certain project"
6
+ flags :author => "Filter commits on a email address of author"
7
+ flags :applies => "Filter commits to patches that apply cleanly"
8
+ flags :noapply => "Filter commits to patches that do not apply cleanly"
9
+ flags :nocache => "Do not use the cached network data"
10
+ flags :cache => "Use the network data even if it's expired"
11
+ flags :sort => "How to sort : date(*), branch, author"
12
+ flags :common => "Show common branch point"
13
+ flags :thisbranch => "Look at branches that match the current one"
14
+ flags :limit => "Only look through the first X heads - useful for really large projects"
15
+ command :network do |command, user|
16
+ return if !helper.project
17
+ user ||= helper.owner
18
+
19
+ case command
20
+ when 'web'
21
+ helper.open helper.network_page_for(user)
22
+ when 'list'
23
+ members = helper.get_network_members(user, options)
24
+ members.each do |hsh|
25
+ puts hsh["owner"]["login"]
26
+ end
27
+ when 'fetch'
28
+ # fetch each remote we don't have
29
+ data = helper.get_network_data(user, options)
30
+ data['users'].each do |hsh|
31
+ u = hsh['name']
32
+ GitHub.invoke(:track, u) unless helper.tracking?(u)
33
+ puts "fetching #{u}"
34
+ GitHub.invoke(:fetch_all, u)
35
+ end
36
+ when 'commits'
37
+ # show commits we don't have yet
38
+
39
+ $stderr.puts 'gathering heads'
40
+ cherry = []
41
+
42
+ if helper.cache_commits_data(options)
43
+ ids = []
44
+ data = helper.get_network_data(user, options)
45
+ data['users'].each do |hsh|
46
+ u = hsh['name']
47
+ if options[:thisbranch]
48
+ user_ids = hsh['heads'].map { |a| a['id'] if a['name'] == helper.current_branch }.compact
49
+ else
50
+ user_ids = hsh['heads'].map { |a| a['id'] }
51
+ end
52
+ user_ids.each do |id|
53
+ if !helper.has_commit?(id) && helper.cache_expired?
54
+ GitHub.invoke(:track, u) unless helper.tracking?(u)
55
+ puts "fetching #{u}"
56
+ GitHub.invoke(:fetch_all, u)
57
+ end
58
+ end
59
+ ids += user_ids
60
+ end
61
+ ids.uniq!
62
+
63
+ $stderr.puts 'has heads'
64
+
65
+ # check that we have all these shas locally
66
+ local_heads = helper.local_heads
67
+ local_heads_not = local_heads.map { |a| "^#{a}"}
68
+ looking_for = (ids - local_heads) + local_heads_not
69
+ commits = helper.get_commits(looking_for)
70
+
71
+ $stderr.puts 'ID SIZE:' + ids.size.to_s
72
+
73
+ ignores = helper.ignore_sha_array
74
+
75
+ ids.each do |id|
76
+ next if ignores[id] || !commits.assoc(id)
77
+ cherries = helper.get_cherry(id)
78
+ cherries = helper.remove_ignored(cherries, ignores)
79
+ cherry += cherries
80
+ helper.ignore_shas([id]) if cherries.size == 0
81
+ $stderr.puts "checking head #{id} : #{cherry.size.to_s}"
82
+ break if options[:limit] && cherry.size > options[:limit].to_i
83
+ end
84
+ end
85
+
86
+ if cherry.size > 0 || !helper.cache_commits_data(options)
87
+ helper.print_network_cherry_help if !options[:shas]
88
+
89
+ if helper.cache_commits_data(options)
90
+ $stderr.puts "caching..."
91
+ $stderr.puts "commits: " + cherry.size.to_s
92
+ our_commits = cherry.map { |item| c = commits.assoc(item[1]); [item, c] if c }
93
+ our_commits.delete_if { |item| item == nil }
94
+ helper.cache_commits(our_commits)
95
+ else
96
+ $stderr.puts "using cached..."
97
+ our_commits = helper.commits_cache
98
+ end
99
+
100
+ helper.print_commits(our_commits, options)
101
+ else
102
+ puts "no unapplied commits"
103
+ end
104
+ else
105
+ helper.print_network_help
106
+ end
107
+ end
108
+
109
+ desc "Ignore a SHA (from 'github network commits')"
110
+ command :ignore do |sha|
111
+ commits = helper.resolve_commits(sha)
112
+ helper.ignore_shas(commits) # add to .git/ignore-shas file
113
+ end
data/lib/github.rb ADDED
@@ -0,0 +1,173 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'github/extensions'
3
+ require 'github/command'
4
+ require 'github/helper'
5
+ require 'fileutils'
6
+ require 'rubygems'
7
+ require 'open-uri'
8
+ require 'json'
9
+ require 'yaml'
10
+
11
+ ##
12
+ # Starting simple.
13
+ #
14
+ # $ github <command> <args>
15
+ #
16
+ # GitHub.command <command> do |*args|
17
+ # whatever
18
+ # end
19
+ #
20
+
21
+ module GitHub
22
+ extend self
23
+
24
+ BasePath = File.expand_path(File.dirname(__FILE__))
25
+
26
+ def command(command, options = {}, &block)
27
+ command = command.to_s
28
+ debug "Registered `#{command}`"
29
+ descriptions[command] = @next_description if @next_description
30
+ @next_description = nil
31
+ flag_descriptions[command].update @next_flags if @next_flags
32
+ usage_descriptions[command] = @next_usage if @next_usage
33
+ @next_flags = nil
34
+ @next_usage = []
35
+ commands[command] = Command.new(block)
36
+ Array(options[:alias] || options[:aliases]).each do |command_alias|
37
+ commands[command_alias.to_s] = commands[command.to_s]
38
+ end
39
+ end
40
+
41
+ def desc(str)
42
+ @next_description = str
43
+ end
44
+
45
+ def flags(hash)
46
+ @next_flags ||= {}
47
+ @next_flags.update hash
48
+ end
49
+
50
+ def usage(string)
51
+ @next_usage ||= []
52
+ @next_usage << string
53
+ end
54
+
55
+ def helper(command, &block)
56
+ debug "Helper'd `#{command}`"
57
+ Helper.send :define_method, command, &block
58
+ end
59
+
60
+ def activate(args)
61
+ @@original_args = args.clone
62
+ @options = parse_options(args)
63
+ @debug = @options.delete(:debug)
64
+ @learn = @options.delete(:learn)
65
+ Dir[BasePath + '/commands/*.rb'].each do |command|
66
+ load command
67
+ end
68
+ invoke(args.shift, *args)
69
+ end
70
+
71
+ def invoke(command, *args)
72
+ block = find_command(command)
73
+ debug "Invoking `#{command}`"
74
+ block.call(*args)
75
+ end
76
+
77
+ def find_command(name)
78
+ name = name.to_s
79
+ commands[name] || GitCommand.new(name) || commands['default']
80
+ end
81
+
82
+ def commands
83
+ @commands ||= {}
84
+ end
85
+
86
+ def descriptions
87
+ @descriptions ||= {}
88
+ end
89
+
90
+ def flag_descriptions
91
+ @flagdescs ||= Hash.new { |h, k| h[k] = {} }
92
+ end
93
+
94
+ def usage_descriptions
95
+ @usage_descriptions ||= Hash.new { |h, k| h[k] = [] }
96
+ end
97
+
98
+ def options
99
+ @options
100
+ end
101
+
102
+ def original_args
103
+ @@original_args ||= []
104
+ end
105
+
106
+ def parse_options(args)
107
+ idx = 0
108
+ args.clone.inject({}) do |memo, arg|
109
+ case arg
110
+ when /^--(.+?)=(.*)/
111
+ args.delete_at(idx)
112
+ memo.merge($1.to_sym => $2)
113
+ when /^--(.+)/
114
+ args.delete_at(idx)
115
+ memo.merge($1.to_sym => true)
116
+ when "--"
117
+ args.delete_at(idx)
118
+ return memo
119
+ else
120
+ idx += 1
121
+ memo
122
+ end
123
+ end
124
+ end
125
+
126
+ def debug(*messages)
127
+ puts *messages.map { |m| "== #{m}" } if debug?
128
+ end
129
+
130
+ def learn(message)
131
+ if learn?
132
+ puts "== " + Color.yellow(message)
133
+ else
134
+ debug(message)
135
+ end
136
+ end
137
+
138
+ def learn?
139
+ !!@learn
140
+ end
141
+
142
+ def debug?
143
+ !!@debug
144
+ end
145
+
146
+ def load(file)
147
+ file[0] =~ /^\// ? path = file : path = BasePath + "/commands/#{File.basename(file)}"
148
+ data = File.read(path)
149
+ GitHub.module_eval data, path
150
+ end
151
+ end
152
+
153
+ GitHub.command :default, :aliases => ['', '-h', 'help', '-help', '--help'] do
154
+ puts "Usage: github command <space separated arguments>", ''
155
+ puts "Available commands:", ''
156
+ longest = GitHub.descriptions.map { |d,| d.to_s.size }.max
157
+ GitHub.descriptions.sort {|a,b| a.to_s <=> b.to_s }.each do |command, desc|
158
+ cmdstr = "%-#{longest}s" % command
159
+ puts " #{cmdstr} => #{desc}"
160
+ flongest = GitHub.flag_descriptions[command].map { |d,| "--#{d}".size }.max
161
+ GitHub.usage_descriptions[command].each do |usage_descriptions|
162
+ usage_descriptions.each do |usage|
163
+ usage_str = "#{" " * longest} %% %-#{flongest}s" % usage
164
+ puts usage_str
165
+ end
166
+ end
167
+ GitHub.flag_descriptions[command].each do |flag, fdesc|
168
+ flagstr = "#{" " * longest} %-#{flongest}s" % "--#{flag}"
169
+ puts " #{flagstr}: #{fdesc}"
170
+ end
171
+ end
172
+ puts
173
+ end
@@ -0,0 +1,129 @@
1
+ require 'fileutils'
2
+
3
+ if RUBY_PLATFORM =~ /mswin|mingw/
4
+ begin
5
+ require 'win32/open3'
6
+ rescue LoadError
7
+ warn "You must 'gem install win32-open3' to use the github command on Windows"
8
+ exit 1
9
+ end
10
+ else
11
+ require 'open3'
12
+ end
13
+
14
+ module GitHub
15
+ class Command
16
+ include FileUtils
17
+
18
+ def initialize(block)
19
+ (class << self;self end).send :define_method, :command, &block
20
+ end
21
+
22
+ def call(*args)
23
+ arity = method(:command).arity
24
+ args << nil while args.size < arity
25
+ send :command, *args
26
+ end
27
+
28
+ def helper
29
+ @helper ||= Helper.new
30
+ end
31
+
32
+ def options
33
+ GitHub.options
34
+ end
35
+
36
+ def pgit(*command)
37
+ puts git(*command)
38
+ end
39
+
40
+ def git(command)
41
+ run :sh, command
42
+ end
43
+
44
+ def git_exec(command)
45
+ run :exec, command
46
+ end
47
+
48
+ def run(method, command)
49
+ if command.is_a? Array
50
+ command = [ 'git', command ].flatten
51
+ GitHub.learn command.join(' ')
52
+ else
53
+ command = 'git ' + command
54
+ GitHub.learn command
55
+ end
56
+
57
+ send method, *command
58
+ end
59
+
60
+ def sh(*command)
61
+ Shell.new(*command).run
62
+ end
63
+
64
+ def die(message)
65
+ puts "=> #{message}"
66
+ exit!
67
+ end
68
+
69
+ def github_user
70
+ git("config --get github.user")
71
+ end
72
+
73
+ def github_token
74
+ git("config --get github.token")
75
+ end
76
+
77
+ def shell_user
78
+ ENV['USER']
79
+ end
80
+
81
+ def current_user?(user)
82
+ user == github_user || user == shell_user
83
+ end
84
+
85
+ class Shell < String
86
+ attr_reader :error
87
+ attr_reader :out
88
+
89
+ def initialize(*command)
90
+ @command = command
91
+ end
92
+
93
+ def run
94
+ GitHub.debug "sh: #{command}"
95
+ _, out, err = Open3.popen3(*@command)
96
+
97
+ out = out.read.strip
98
+ err = err.read.strip
99
+
100
+ replace @error = err if err.any?
101
+ replace @out = out if out.any?
102
+
103
+ self
104
+ end
105
+
106
+ def command
107
+ @command.join(' ')
108
+ end
109
+
110
+ def error?
111
+ !!@error
112
+ end
113
+
114
+ def out?
115
+ !!@out
116
+ end
117
+ end
118
+ end
119
+
120
+ class GitCommand < Command
121
+ def initialize(name)
122
+ @name = name
123
+ end
124
+
125
+ def command(*args)
126
+ git_exec [ @name, args ]
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,39 @@
1
+ # define #try
2
+ class Object
3
+ def try
4
+ self
5
+ end
6
+ end
7
+
8
+ class NilClass
9
+ klass = Class.new
10
+ klass.class_eval do
11
+ instance_methods.each { |meth| undef_method meth.to_sym unless meth =~ /^__(id|send)__$/ }
12
+ def method_missing(*args)
13
+ self
14
+ end
15
+ end
16
+ NilProxy = klass.new
17
+ def try
18
+ NilProxy
19
+ end
20
+ end
21
+
22
+ # define #tap
23
+ class Object
24
+ def tap(&block)
25
+ block.call(self)
26
+ self
27
+ end
28
+ end
29
+
30
+ # cute
31
+ module Color
32
+ COLORS = { :clear => 0, :red => 31, :green => 32, :yellow => 33 }
33
+ def self.method_missing(color_name, *args)
34
+ color(color_name) + args.first + color(:clear)
35
+ end
36
+ def self.color(color)
37
+ "\e[#{COLORS[color.to_sym]}m"
38
+ end
39
+ end