projector 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +47 -0
- data/Rakefile +2 -0
- data/bin/projector +17 -0
- data/lib/projector/cli.rb +65 -0
- data/lib/projector/helpers.rb +63 -0
- data/lib/projector/repo.rb +17 -0
- data/lib/projector/version.rb +3 -0
- data/lib/projector.rb +7 -0
- data/projector.gemspec +22 -0
- metadata +105 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Projector
|
2
|
+
|
3
|
+
A simple command-line app to keep your projects directory up to date with all of your Github projects. I got tired of having to re-clone new projects all the time, and figured there had to be an easier way...so here it is.
|
4
|
+
|
5
|
+
## Dependencies
|
6
|
+
|
7
|
+
Requires the [Thor](https://github.com/wycats/thor) and JSON gems. See the gemspec for more info.
|
8
|
+
|
9
|
+
## Installation and Usage
|
10
|
+
|
11
|
+
1. Install the gem
|
12
|
+
|
13
|
+
gem install projector
|
14
|
+
|
15
|
+
2. Configure your Github settings (if you haven't done so already). Details are [here](http://help.github.com/set-your-user-name-email-and-github-token/), but the short version is:
|
16
|
+
|
17
|
+
git config --global github.user <username>
|
18
|
+
git config --global github.token <token>
|
19
|
+
|
20
|
+
3. Configure your working directory
|
21
|
+
|
22
|
+
# For me, I have a Projects directory under my home directory where I keep all of my working copies. Adjust to fit your own conventions.
|
23
|
+
git config --global projector.workingdir ~/Projects
|
24
|
+
|
25
|
+
4. Run projector update
|
26
|
+
|
27
|
+
Projector will find all of the repos you have access to and prompt you to clone them under your working directory if they're not already cloned. By default, it will create a nested directory structure based on the repository owner, something like this:
|
28
|
+
|
29
|
+
jayzes/
|
30
|
+
jayzes/projector
|
31
|
+
jayzes/cucumber-api-steps
|
32
|
+
gvarela/
|
33
|
+
gvarela/food_court_recipes
|
34
|
+
|
35
|
+
If you want it to forge ahead and clone everything, there's a -y option that assumes yes to every clone confirmation and doesn't bother prompting.
|
36
|
+
|
37
|
+
## Future Ideas
|
38
|
+
* Skiplist/repo ignore regexes
|
39
|
+
* Checking for repos that aren't under version control and prompting to create or prune them
|
40
|
+
* An easier way to run this under cron
|
41
|
+
|
42
|
+
# Author
|
43
|
+
Jay Zeschin
|
44
|
+
|
45
|
+
## Copyright
|
46
|
+
|
47
|
+
Copyright (c) 2011 Jay Zeschin. Distributed under the MIT License.
|
data/Rakefile
ADDED
data/bin/projector
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
# Requires
|
5
|
+
begin
|
6
|
+
require 'projector'
|
7
|
+
rescue LoadError
|
8
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
|
9
|
+
require 'rubygems'
|
10
|
+
require 'projector'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Setup Constants
|
14
|
+
Projector::GEM_ROOT = File.expand_path( File.dirname( __FILE__ ) + '/../' )
|
15
|
+
|
16
|
+
# Run
|
17
|
+
Projector::CLI.start
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'thor/actions'
|
3
|
+
|
4
|
+
module Projector
|
5
|
+
|
6
|
+
class CLI < Thor
|
7
|
+
|
8
|
+
# Includes
|
9
|
+
include Thor::Actions
|
10
|
+
include Projector::Helpers
|
11
|
+
|
12
|
+
# Tasks
|
13
|
+
desc "check", "Check Git settings to make sure Projector can work its magic properly"
|
14
|
+
long_desc <<-DESC
|
15
|
+
Projector will check to make sure that your Git settings contain your Github username
|
16
|
+
and API key (see http://help.github.com/set-your-user-name-email-and-github-token/)
|
17
|
+
as well as your preferred working directory
|
18
|
+
DESC
|
19
|
+
def check
|
20
|
+
unless github_username?
|
21
|
+
say 'You need to configure your github.user setting - "git config --global github.user <username>" should do the trick'
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
unless github_token?
|
25
|
+
say 'You need to configure your github.token setting - "git config --global github.token <token>" should do the trick'
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
unless projector_working_dir?
|
29
|
+
say 'You need to configure your projector.workingdir setting - "git config --global projector.workingdir <directory>" should do the trick'
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
desc "update", "Go through the Github repositories you can access and ensure that working copies for them are cloned into your working directory"
|
36
|
+
long_desc <<-DESC
|
37
|
+
Projector loop through all of the repositories that you can access and clone working
|
38
|
+
copies of them under your configured working directory if they don't already exist
|
39
|
+
DESC
|
40
|
+
method_option :yes, :type => :boolean, :aliases => "-y"
|
41
|
+
def update
|
42
|
+
invoke :check
|
43
|
+
|
44
|
+
repos = all_repos
|
45
|
+
|
46
|
+
say "Checking #{repos.size} repositories"
|
47
|
+
repos.each do |repo|
|
48
|
+
say "Looking at #{repo.path}"
|
49
|
+
if !repo_cloned?(repo) && (options[:yes] || yes?("Repo #{repo.path} is not cloned yet. Clone it? (y/n)"))
|
50
|
+
say "Cloning #{repo.clone_url} to #{repo.clone_path(projector_working_dir)}"
|
51
|
+
repo.clone(projector_working_dir)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
desc "version", "Prints Projector's version information"
|
58
|
+
def version
|
59
|
+
say "Projector version #{Projector::VERSION}"
|
60
|
+
end
|
61
|
+
map %w(-v --version) => :version
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "net/https"
|
2
|
+
require "uri"
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Projector
|
6
|
+
module Helpers
|
7
|
+
def github_username
|
8
|
+
`git config --get github.user`.strip
|
9
|
+
end
|
10
|
+
|
11
|
+
def github_username?
|
12
|
+
github_username && github_username.length > 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def github_token
|
16
|
+
`git config --get github.token`.strip
|
17
|
+
end
|
18
|
+
|
19
|
+
def github_token?
|
20
|
+
github_token && github_token.length > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def projector_working_dir
|
24
|
+
`git config --get projector.workingdir`.strip
|
25
|
+
end
|
26
|
+
|
27
|
+
def projector_working_dir?
|
28
|
+
projector_working_dir && projector_working_dir.length > 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def repo_cloned?(repo)
|
32
|
+
File.directory?(File.join(repo.clone_path(projector_working_dir), '.git'))
|
33
|
+
end
|
34
|
+
|
35
|
+
def user_repos
|
36
|
+
repo_api_request("https://github.com/api/v2/json/repos/show/#{github_username}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def organization_repos
|
40
|
+
repo_api_request("https://github.com/api/v2/json/organizations/repositories?owned=1")
|
41
|
+
end
|
42
|
+
|
43
|
+
def collaborator_repos
|
44
|
+
repo_api_request("https://github.com/api/v2/json/repos/pushable")
|
45
|
+
end
|
46
|
+
|
47
|
+
def all_repos
|
48
|
+
(user_repos + organization_repos + collaborator_repos).uniq
|
49
|
+
end
|
50
|
+
|
51
|
+
def repo_api_request(endpoint)
|
52
|
+
uri = URI.parse(endpoint)
|
53
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
54
|
+
http.use_ssl = true
|
55
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # TODO: http://www.rubyinside.com/how-to-cure-nethttps-risky-default-https-behavior-4010.html
|
56
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
57
|
+
request.basic_auth("#{github_username}/token", github_token)
|
58
|
+
response = http.request(request)
|
59
|
+
JSON.parse(response.body)['repositories'].map { |repo| Repo.new(repo['owner'], repo['name']) }
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Repo = Struct.new(:owner, :name) do
|
2
|
+
def path
|
3
|
+
"#{self.owner}/#{self.name}"
|
4
|
+
end
|
5
|
+
|
6
|
+
def clone_path(base_dir)
|
7
|
+
File.join(base_dir, self.owner, self.name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def clone_url
|
11
|
+
"git@github.com:#{self.owner}/#{self.name}.git"
|
12
|
+
end
|
13
|
+
|
14
|
+
def clone(base_dir)
|
15
|
+
system("git clone #{clone_url} #{clone_path(base_dir)}")
|
16
|
+
end
|
17
|
+
end
|
data/lib/projector.rb
ADDED
data/projector.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "projector/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "projector"
|
7
|
+
s.version = Projector::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jay Zeschin"]
|
10
|
+
s.email = ["jay@zeschin.org"]
|
11
|
+
s.homepage = "https://github.com/jayzes/projector"
|
12
|
+
s.summary = %q{Automatically keep a working directory with checkouts of all your Github projects}
|
13
|
+
s.description = %q{Automatically keep a working directory with checkouts of all your Github projects}
|
14
|
+
|
15
|
+
s.add_dependency 'json'
|
16
|
+
s.add_dependency 'thor'
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: projector
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jay Zeschin
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-06-08 00:00:00 -06:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: json
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: thor
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
description: Automatically keep a working directory with checkouts of all your Github projects
|
50
|
+
email:
|
51
|
+
- jay@zeschin.org
|
52
|
+
executables:
|
53
|
+
- projector
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
58
|
+
files:
|
59
|
+
- .gitignore
|
60
|
+
- Gemfile
|
61
|
+
- README.md
|
62
|
+
- Rakefile
|
63
|
+
- bin/projector
|
64
|
+
- lib/projector.rb
|
65
|
+
- lib/projector/cli.rb
|
66
|
+
- lib/projector/helpers.rb
|
67
|
+
- lib/projector/repo.rb
|
68
|
+
- lib/projector/version.rb
|
69
|
+
- projector.gemspec
|
70
|
+
has_rdoc: true
|
71
|
+
homepage: https://github.com/jayzes/projector
|
72
|
+
licenses: []
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 3
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: "0"
|
97
|
+
requirements: []
|
98
|
+
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.3.7
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Automatically keep a working directory with checkouts of all your Github projects
|
104
|
+
test_files: []
|
105
|
+
|