gisty 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+
2
+ = gisty
3
+
4
+
5
+ == Description
6
+
7
+ yet another command line client for gist
8
+
9
+ == Installation
10
+
11
+ === Gem Installation
12
+
13
+ gem sources -a http://gems.github.com (you only have to do this once)
14
+ sudo gem install swdyh-gisty
15
+
16
+ set environment variable GISTY_DIR.
17
+ example .zshrc
18
+
19
+ export GISTY_DIR="$HOME/dev/gists"
20
+
21
+ set global git config. see "Global Git Config" at https://github.com/account
22
+
23
+ git config --global github.user your_id
24
+ git config --global github.token your_token
25
+
26
+ if you use zsh command completion, download this file to $fpath directory.
27
+ http://github.com/swdyh/gisty/raw/master/_gisty
28
+
29
+
30
+ == Features/Problems
31
+
32
+ use API token with HTTP. at your own risk.
33
+
34
+ == Synopsis
35
+
36
+ gisty list show local list.
37
+ gisty post file1 file2 ... post new gist.
38
+ gisty private_post file1 file2 ... post new private gist.
39
+ gisty sync sync remote gist. (clone all remote gist)
40
+ gisty sync_delete sync remote gist. delete local gist if remote gist was deleted.
41
+ gisty pull_all pull all gist.
42
+ gisty about show about gisty
43
+ gisty help show help
44
+
45
+ == Copyright
46
+
47
+ Author:: swdyh <http://mailhide.recaptcha.net/d?k=01AhB7crgrlHptVaYRD0oPwA==&c=L_iqOZrGmo6hcGpPTFg1QYnjr-WpAStyQ4Y8ShfgOHs=>
48
+ Copyright:: Copyright (c) 2008 swdyh
49
+ License:: MIT
@@ -0,0 +1,118 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'rake/contrib/sshpublisher'
10
+ require 'fileutils'
11
+ require 'lib/gisty'
12
+ include FileUtils
13
+
14
+ NAME = "gisty"
15
+ AUTHOR = "swdyh"
16
+ EMAIL = "http://mailhide.recaptcha.net/d?k=01AhB7crgrlHptVaYRD0oPwA==&c=L_iqOZrGmo6hcGpPTFg1QYnjr-WpAStyQ4Y8ShfgOHs="
17
+ DESCRIPTION = "yet another command line client for gist"
18
+ RUBYFORGE_PROJECT = "gisty"
19
+ HOMEPATH = "http://github.com/swdyh/gisty/tree/master"
20
+ BIN_FILES = %w( gisty )
21
+
22
+ VERS = Gisty::VERSION
23
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
24
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', '*.gemspec']
25
+ RDOC_OPTS = [
26
+ '--title', "#{NAME} documentation",
27
+ "--charset", "utf-8",
28
+ "--line-numbers",
29
+ "--main", "README.rdoc",
30
+ "--inline-source",
31
+ ]
32
+
33
+ task :default => [:test]
34
+ task :package => [:clean]
35
+
36
+ Rake::TestTask.new("test") do |t|
37
+ t.libs << "test"
38
+ t.pattern = "test/**/*_test.rb"
39
+ t.verbose = true
40
+ end
41
+
42
+ spec = Gem::Specification.new do |s|
43
+ s.name = NAME
44
+ s.version = VERS
45
+ s.platform = Gem::Platform::RUBY
46
+ s.has_rdoc = true
47
+ s.extra_rdoc_files = ["README.rdoc"]
48
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
49
+ s.summary = DESCRIPTION
50
+ s.description = DESCRIPTION
51
+ s.author = AUTHOR
52
+ s.email = EMAIL
53
+ s.homepage = HOMEPATH
54
+ s.executables = BIN_FILES
55
+ s.rubyforge_project = RUBYFORGE_PROJECT
56
+ s.bindir = "bin"
57
+ s.require_path = "lib"
58
+ #s.autorequire = ""
59
+ s.test_files = Dir["test/*_test.rb"]
60
+
61
+ #s.add_dependency('activesupport', '>=1.3.1')
62
+ s.add_dependency('nokogiri', '>=1.0.0')
63
+ #s.required_ruby_version = '>= 1.8.2'
64
+
65
+ s.files = %w(README.rdoc Rakefile) +
66
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
67
+ Dir.glob("ext/**/*.{h,c,rb}") +
68
+ Dir.glob("examples/**/*.rb") +
69
+ Dir.glob("tools/*.rb") +
70
+ Dir.glob("rails/*.rb")
71
+
72
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
73
+ end
74
+
75
+
76
+ Rake::GemPackageTask.new(spec) do |p|
77
+ p.need_tar = true
78
+ p.gem_spec = spec
79
+ end
80
+
81
+ Rake::RDocTask.new do |rdoc|
82
+ rdoc.rdoc_dir = 'html'
83
+ rdoc.options += RDOC_OPTS
84
+ rdoc.template = "resh"
85
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
86
+ if ENV['DOC_FILES']
87
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
88
+ else
89
+ rdoc.rdoc_files.include('README.rdoc')
90
+ rdoc.rdoc_files.include('lib/**/*.rb')
91
+ rdoc.rdoc_files.include('ext/**/*.c')
92
+ end
93
+ end
94
+
95
+ desc 'Update gem spec'
96
+ task :gemspec do
97
+ open("#{NAME}.gemspec", 'w') { |f| f.puts spec.to_ruby }
98
+ end
99
+
100
+ desc 'gem build'
101
+ task :build_gem => [:gemspec] do
102
+ sh "gem build #{NAME}.gemspec"
103
+ end
104
+
105
+ desc 'refresh fixtures'
106
+ task :reflresh_fixtures do
107
+ g = Gisty.new 'tmp'
108
+ re = /page=\d+/
109
+ urls = g.map_pages do |url, page|
110
+ m = url.match re
111
+ if m
112
+ fn = 'mine_' + m.to_a.first.sub('=', '_') + '_login_foo_token_bar'
113
+ path = File.join 'test', 'fixtures', fn
114
+ puts "write #{path}"
115
+ open(path, 'w') { |f| f.write page.gsub(/(&amp;)?(login|token)=\w+(&amp;)?/, '') }
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'gisty'
5
+
6
+ @cmds = {}
7
+
8
+ def cmd name
9
+ @cmds[name.to_s] = Proc.new { |i| yield i }
10
+ end
11
+
12
+ cmd :about do
13
+ puts Gisty::AA
14
+ puts
15
+ puts 'version: ' + Gisty::VERSION
16
+ puts 'url: ' + Gisty::GISTY_URL
17
+ end
18
+
19
+ cmd :help do
20
+ puts <<-EOS
21
+ usage:
22
+ gisty commands
23
+ commands:
24
+ gisty list show local list.
25
+ gisty post file1 file2 ... post new gist.
26
+ gisty private_post file1 file2 ... post new private gist.
27
+ gisty sync sync remote gist. (clone all remote gist)
28
+ gisty sync_delete sync remote gist. delete local gist if remote gist was deleted.
29
+ gisty pull_all pull all gist.
30
+ gisty about show about gisty
31
+ gisty help show help
32
+ EOS
33
+ end
34
+
35
+ cmd :list do
36
+ list = @g.list
37
+ puts '- public gist -'
38
+ list[:public].each do |i|
39
+ puts "#{i[0]}: #{i[1].join(' ')}"
40
+ end
41
+ puts '- private gist -'
42
+ list[:private].each do |i|
43
+ puts "#{i[0]}: #{i[1].join(' ')}"
44
+ end
45
+ end
46
+
47
+ cmd :sync do
48
+ @g.sync
49
+ puts '---'
50
+ puts 'sync finished.'
51
+ end
52
+
53
+ cmd :sync_delete do
54
+ @g.sync true
55
+ puts '---'
56
+ puts 'sync finished.'
57
+ end
58
+
59
+ cmd :pull_all do
60
+ @g.pull_all
61
+ puts '---'
62
+ puts 'pull_all finished.'
63
+ end
64
+
65
+ cmd :post do |fs|
66
+ if fs.size > 0
67
+ begin
68
+ url = @g.create fs
69
+ rescue Gisty::InvalidFileException => e
70
+ puts "Error: invalid file"
71
+ rescue Exception => e
72
+ puts "Error: #{e}"
73
+ else
74
+ id = url.split('/').last
75
+ @g.clone id
76
+ system "open #{url}" if /darwin/ === RUBY_PLATFORM
77
+ end
78
+ end
79
+ end
80
+
81
+ cmd :private_post do |fs|
82
+ if fs.size > 0
83
+ begin
84
+ url = @g.create fs, :private => true
85
+ rescue Exception => e
86
+ puts "Error: #{e}"
87
+ else
88
+ system "open #{url}" if /darwin/ === RUBY_PLATFORM
89
+ id = url.split('/').last
90
+ @g.clone id
91
+ end
92
+ end
93
+ end
94
+
95
+
96
+ if ENV['GISTY_DIR']
97
+ begin
98
+ @g = Gisty.new ENV['GISTY_DIR']
99
+ rescue Gisty::UnsetAuthInfoException => e
100
+ puts 'Error: set your api token.'
101
+ puts 'see Global Git Config at https://github.com/account'
102
+ exit
103
+ end
104
+ else
105
+ puts "Error: please set ENV['GISTY_DIR']"
106
+ exit
107
+ end
108
+
109
+ if ARGV.size == 0
110
+ @cmds['help'].call []
111
+ else
112
+ c = @cmds[ARGV.first]
113
+ if c
114
+ c.call ARGV.last(ARGV.size - 1)
115
+ else
116
+ puts 'unknown commands.'
117
+ end
118
+ end
119
+
@@ -0,0 +1,194 @@
1
+ require 'pathname'
2
+ require 'net/http'
3
+ require 'open-uri'
4
+ require 'fileutils'
5
+ require 'rubygems'
6
+ require 'nokogiri'
7
+
8
+ class Gisty
9
+ VERSION = '0.0.15'
10
+ GIST_URL = 'http://gist.github.com/'
11
+ GISTY_URL = 'http://github.com/swdyh/gisty/tree/master'
12
+
13
+ class UnsetAuthInfoException < Exception
14
+ end
15
+
16
+ class InvalidFileException < Exception
17
+ end
18
+
19
+ class PostFailureException < Exception
20
+ end
21
+
22
+ def self.extract_ids str
23
+ doc = Nokogiri::HTML str
24
+ doc.css('.file .info a').map { |i| i['href'].sub('/', '') }
25
+ end
26
+
27
+ def self.extract url
28
+ doc = Nokogiri::HTML open(url)
29
+ {
30
+ :id => url.split('/').last,
31
+ :author => doc.css('#owner a').inner_text,
32
+ :files => doc.css('.meta .info').map { |i| i.inner_text.strip },
33
+ :clone => doc.css('a[rel="#git-clone"]').inner_text,
34
+ }
35
+ end
36
+
37
+ def initialize path, login = nil, token = nil
38
+ @auth = (login && token) ? { 'login' => login, 'token' => token } : auth
39
+ raise UnsetAuthInfoException if @auth['login'].nil? || @auth['token'].nil?
40
+ @auth_query = "login=#{@auth['login']}&token=#{@auth['token']}"
41
+ @dir = Pathname.pwd.realpath.join path
42
+ FileUtils.mkdir_p @dir unless @dir.exist?
43
+ end
44
+
45
+ def next_link str
46
+ doc = Nokogiri::HTML str
47
+ a = doc.at('.pagination a[hotkey="l"]')
48
+ a ? a['href'] : nil
49
+ end
50
+
51
+ def map_pages
52
+ result = []
53
+ base_url = GIST_URL.sub(/\/$/, '')
54
+ path = "/mine?page=1"
55
+ loop do
56
+ url = base_url + path + "&#{@auth_query}"
57
+ page = open(url).read
58
+ result << yield(url, page)
59
+ path = next_link page
60
+ break unless path
61
+ end
62
+ result
63
+ end
64
+
65
+ def remote_ids
66
+ map_pages { |url, page| Gisty.extract_ids page }.flatten.uniq.sort
67
+ end
68
+
69
+ def clone id
70
+ FileUtils.cd @dir do
71
+ c = "git clone git@gist.github.com:#{id}.git"
72
+ Kernel.system c
73
+ end
74
+ end
75
+
76
+ def list
77
+ dirs = Pathname.glob(@dir.to_s + '/*').map do |i|
78
+ [i.basename.to_s,
79
+ Pathname.glob(i.to_s + '/*').map { |i| i.basename.to_s }]
80
+ end
81
+ re_pub = /^\d+$/
82
+ pub = dirs.select { |i| re_pub.match(i.first) }.sort_by { |i| i.first.to_i }.reverse
83
+ pri = dirs.select { |i| !re_pub.match(i.first) }.sort_by { |i| i.first }
84
+ { :public => pub, :private => pri }
85
+ end
86
+
87
+ def local_ids
88
+ dirs = Pathname.glob(@dir.to_s + '/*')
89
+ dirs.map { |i| i.basename.to_s }
90
+ end
91
+
92
+ def delete id
93
+ FileUtils.rm_rf @dir.join(id) if @dir.join(id).exist?
94
+ end
95
+
96
+ def sync delete = false
97
+ remote = remote_ids
98
+ local = local_ids
99
+
100
+ if delete
101
+ (local - remote).each do |id|
102
+ print "delete #{id}? [y/n]"
103
+ confirm = $stdin.gets.strip
104
+ if confirm == 'y' || confirm == 'yes'
105
+ puts "delete #{id}"
106
+ delete id
107
+ else
108
+ puts "skip #{id}"
109
+ end
110
+ end
111
+ ids = remote
112
+ else
113
+ ids = (remote + local).uniq
114
+ end
115
+
116
+ FileUtils.cd @dir do
117
+ ids.each do |id|
118
+ if File.exist? id
119
+ # FileUtils.cd id do
120
+ # c = "git pull"
121
+ # Kernel.system c
122
+ # end
123
+ else
124
+ c = "git clone git@gist.github.com:#{id}.git"
125
+ Kernel.system c
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ def pull_all
132
+ ids = local_ids
133
+ FileUtils.cd @dir do
134
+ ids.each do |id|
135
+ if File.exist? id
136
+ FileUtils.cd id do
137
+ c = "git pull"
138
+ Kernel.system c
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ def auth
146
+ user = `git config --global github.user`.strip
147
+ token = `git config --global github.token`.strip
148
+ user.empty? ? {} : { 'login' => user, 'token' => token }
149
+ end
150
+
151
+ def post params
152
+ url = URI.parse('http://gist.github.com/gists')
153
+ res = Net::HTTP.post_form(url, params)
154
+ if res['Location']
155
+ res['Location']
156
+ else
157
+ raise PostFailureException, res.inspect
158
+ end
159
+ end
160
+
161
+ def build_params paths
162
+ list = (Array === paths ? paths : [paths]).map { |i| Pathname.new i }
163
+ raise InvalidFileException if list.any?{ |i| !i.file? }
164
+
165
+ params = {}
166
+ list.each_with_index do |i, index|
167
+ params["file_ext[gistfile#{index + 1}]"] = i.extname
168
+ params["file_name[gistfile#{index + 1}]"] = i.basename.to_s
169
+ params["file_contents[gistfile#{index + 1}]"] = IO.read(i)
170
+ end
171
+ params
172
+ end
173
+
174
+ def create paths, opt = { :private => false }
175
+ params = build_params paths
176
+ if opt[:private]
177
+ params['private'] = 'on'
178
+ params['action_button'] = 'private'
179
+ end
180
+ post params.merge(auth)
181
+ end
182
+
183
+ # `figlet -f contributed/bdffonts/clb8x8.flf gisty`.gsub('#', 'm')
184
+ AA = <<-EOS
185
+ mm mm
186
+ mm
187
+ mmmmmm mmmm mmmmm mmmmmm mm mm
188
+ mm mm mm mm mm mm mm
189
+ mm mm mm mmmm mm mm mm
190
+ mmmmmm mm mm mm mmmmm
191
+ mm mmmmmm mmmmm mmm mm
192
+ mmmmm mmmm
193
+ EOS
194
+ end