88miles 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +81 -0
- data/LICENSE.txt +20 -0
- data/README.md +79 -0
- data/Rakefile +36 -0
- data/VERSION +1 -0
- data/bin/88miles +3 -0
- data/gigawatt.gemspec +89 -0
- data/lib/gigawatt/application.rb +8 -0
- data/lib/gigawatt/cache.rb +71 -0
- data/lib/gigawatt/commands/init.rb +51 -0
- data/lib/gigawatt/commands/log.rb +162 -0
- data/lib/gigawatt/commands/setup.rb +107 -0
- data/lib/gigawatt/commands/start.rb +75 -0
- data/lib/gigawatt/commands/status.rb +101 -0
- data/lib/gigawatt/commands/stop.rb +57 -0
- data/lib/gigawatt/commands/sync.rb +53 -0
- data/lib/gigawatt/oauth.rb +23 -0
- data/lib/gigawatt/options.rb +53 -0
- data/lib/gigawatt/project_file.rb +34 -0
- data/lib/gigawatt/settings.rb +41 -0
- data/lib/gigawatt.rb +29 -0
- data/test/helper.rb +18 -0
- data/test/test_gigawatt.rb +7 -0
- metadata +177 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
module Commands
|
3
|
+
class Setup
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
def self.run!(settings)
|
7
|
+
options = Trollop::options do
|
8
|
+
banner <<-EOS
|
9
|
+
88 Miles Command line application - http://88miles.net
|
10
|
+
|
11
|
+
This command will request an access token, giving the command line utility access to your 88 Miles account.
|
12
|
+
|
13
|
+
To do this, you will be asked for your 88 Miles login and password. Please note that the login and password will not be saved.
|
14
|
+
|
15
|
+
Usage
|
16
|
+
88miles setup [options]
|
17
|
+
|
18
|
+
options:
|
19
|
+
EOS
|
20
|
+
opt :force, "Override existing settings", :default => false, :type => :boolean
|
21
|
+
end
|
22
|
+
|
23
|
+
instance = self.new(settings, options)
|
24
|
+
|
25
|
+
if instance.settings_exists?
|
26
|
+
puts "The settings file #{instance.settings.path} already exists. Use --force to overwrite"
|
27
|
+
return SETTINGS_FILE_EXISTS
|
28
|
+
end
|
29
|
+
|
30
|
+
instance.preamble
|
31
|
+
|
32
|
+
begin
|
33
|
+
instance.authenticate
|
34
|
+
rescue OAuth2::Error => e
|
35
|
+
puts "There was an issue authenticating your account. Please try again."
|
36
|
+
return INVALID_OAUTH_TOKEN_EXIT_CODE
|
37
|
+
end
|
38
|
+
instance.postamble
|
39
|
+
|
40
|
+
return OK_EXIT_CODE
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(settings, options)
|
44
|
+
@options = options
|
45
|
+
@settings = settings
|
46
|
+
end
|
47
|
+
|
48
|
+
def settings
|
49
|
+
@settings
|
50
|
+
end
|
51
|
+
|
52
|
+
def settings_exists?
|
53
|
+
return false if options[:force]
|
54
|
+
@settings.setup?
|
55
|
+
end
|
56
|
+
|
57
|
+
def preamble
|
58
|
+
say("88 Miles command line utility setup")
|
59
|
+
say("-----------------------------------")
|
60
|
+
say("To setup the 88 Miles command line utility, we need to authenticate you and request an access token.")
|
61
|
+
say("We will open a browser, where you will be asked to login and approve access to this app.")
|
62
|
+
end
|
63
|
+
|
64
|
+
def postamble
|
65
|
+
say("Thank you. We can now access your account. You can now initialize a directory by running <%= color('88miles init [directory]', BOLD) %>")
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_access_key(url)
|
69
|
+
uri = URI(url)
|
70
|
+
token = uri.fragment.split('&').map{ |kv| kv.split('=') }.delete_if{ |kv| kv[0] != 'access_token' }.first
|
71
|
+
return token[1] if token
|
72
|
+
return nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def authenticate
|
76
|
+
client = Gigawatt::OAuth.client
|
77
|
+
|
78
|
+
redirect_uri = Gigawatt::OAuth.redirect_uri
|
79
|
+
url = client.auth_code.authorize_url(:response_type => 'token', :redirect_uri => redirect_uri)
|
80
|
+
|
81
|
+
Launchy.open(url) do |exception|
|
82
|
+
say "Couldn't open a browser. Please paste the following URL into a browser"
|
83
|
+
say url
|
84
|
+
end
|
85
|
+
|
86
|
+
say("After you have completed the approval process, cut and paste the URL you are redirected to.")
|
87
|
+
access_key = get_access_key(ask("URL: ") do |url|
|
88
|
+
url.validate = /\A#{redirect_uri}#access_token=.+&state=\Z/
|
89
|
+
url.responses[:not_valid] = "That URL doesn't look right. It should look like: #{redirect_uri}#access_token=[some characters]&state="
|
90
|
+
end)
|
91
|
+
|
92
|
+
@settings.access_key = access_key
|
93
|
+
@access_key = OAuth.token(access_key)
|
94
|
+
|
95
|
+
cache = Gigawatt::Cache.new(@settings, @access_key)
|
96
|
+
|
97
|
+
cache.refresh!
|
98
|
+
|
99
|
+
@settings.companies = cache.companies
|
100
|
+
@settings.projects = cache.projects
|
101
|
+
|
102
|
+
@settings.write(:accesskey)
|
103
|
+
@access_key.token
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
module Commands
|
3
|
+
class Start
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
def self.run!(settings)
|
7
|
+
options = Trollop::options do
|
8
|
+
banner <<-EOS
|
9
|
+
88 Miles Command line application - http://88miles.net
|
10
|
+
|
11
|
+
Punch into the project.
|
12
|
+
|
13
|
+
Usage
|
14
|
+
88miles start [options]
|
15
|
+
|
16
|
+
options:
|
17
|
+
EOS
|
18
|
+
|
19
|
+
|
20
|
+
opt :activity, "Select an activity", :type => :flag
|
21
|
+
end
|
22
|
+
|
23
|
+
instance = self.new(settings, options)
|
24
|
+
begin
|
25
|
+
return instance.punch_in
|
26
|
+
rescue OAuth2::Error => e
|
27
|
+
say "Access to your 88 Miles may have been revoked. Please run <%= color('88miles setup', BOLD) %> again."
|
28
|
+
return INVALID_OAUTH_TOKEN_EXIT_CODE
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(settings, options)
|
33
|
+
@settings = settings
|
34
|
+
@options = options
|
35
|
+
|
36
|
+
@access_key = OAuth.token(@settings.access_key)
|
37
|
+
@cache = Cache.new(settings, @access_key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def select_activity(project)
|
41
|
+
return nil unless options[:activity]
|
42
|
+
return nil unless project["activities"]
|
43
|
+
|
44
|
+
selected = nil
|
45
|
+
choose do |menu|
|
46
|
+
menu.prompt = "Pick an Activity"
|
47
|
+
project["activities"].each do |activity|
|
48
|
+
menu.choice("#{activity["name"]}") { selected = activity }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
selected
|
52
|
+
end
|
53
|
+
|
54
|
+
def punch_in
|
55
|
+
project = Gigawatt::ProjectFile.new.project
|
56
|
+
|
57
|
+
if project
|
58
|
+
activity = select_activity(project)
|
59
|
+
opts = {}
|
60
|
+
opts = { :body => { :activity_uuid => activity["uuid"] } } if activity
|
61
|
+
response = JSON.parse(@access_key.post("/api/1/projects/#{project["uuid"]}/punch_in.json", opts).body)
|
62
|
+
current = response["response"]
|
63
|
+
ProjectFile.write(current)
|
64
|
+
|
65
|
+
company = @cache.companies(true)[project["company_uuid"]]
|
66
|
+
say("Punched in to #{company["name"]}: #{project["name"]}")
|
67
|
+
return OK_EXIT_CODE
|
68
|
+
else
|
69
|
+
say("No project found. Did you remember to run <%= color('88miles init [directory]', BOLD) %>?")
|
70
|
+
return NO_PROJECT_EXIT_CODE
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
module Commands
|
3
|
+
class Status
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
def self.run!(settings)
|
7
|
+
options = Trollop::options do
|
8
|
+
banner <<-EOS
|
9
|
+
88 Miles Command line application - http://88miles.net
|
10
|
+
|
11
|
+
Get status about the linked project
|
12
|
+
|
13
|
+
Usage:
|
14
|
+
88miles status [options]
|
15
|
+
|
16
|
+
options:
|
17
|
+
EOS
|
18
|
+
|
19
|
+
opt :sync, "Sync the data from the server first. Uses the cache if false", :type => :flag
|
20
|
+
opt :foreground, "Don't exit - just refresh the timer", :type => :flag
|
21
|
+
opt :time, "Only return the time", :type => :flag
|
22
|
+
end
|
23
|
+
|
24
|
+
instance = self.new(settings, options)
|
25
|
+
return instance.get_settings
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(settings, options)
|
29
|
+
@settings = settings
|
30
|
+
@options = options
|
31
|
+
|
32
|
+
@access_key = OAuth.token(@settings.access_key)
|
33
|
+
@cache = Cache.new(settings, @access_key)
|
34
|
+
|
35
|
+
@project = Gigawatt::ProjectFile.new.project
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_settings
|
39
|
+
unless @project
|
40
|
+
say("No project found.")
|
41
|
+
return NO_PROJECT_EXIT_CODE
|
42
|
+
end
|
43
|
+
|
44
|
+
if @options[:sync]
|
45
|
+
sync = Gigawatt::Commands::Sync.new(@settings, @options)
|
46
|
+
begin
|
47
|
+
sync.sync
|
48
|
+
sync.sync_current
|
49
|
+
rescue OAuth2::Error => e
|
50
|
+
say "Access to your 88 Miles may have been revoked. Please run <%= color('88miles setup', BOLD) %> again."
|
51
|
+
return INVALID_OAUTH_TOKEN_EXIT_CODE
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if @options[:foreground]
|
56
|
+
while(1)
|
57
|
+
print_status
|
58
|
+
sleep(1)
|
59
|
+
end
|
60
|
+
print "\n"
|
61
|
+
else
|
62
|
+
print_status
|
63
|
+
print "\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
return OK_EXIT_CODE
|
67
|
+
end
|
68
|
+
|
69
|
+
def print_status
|
70
|
+
company = @cache.companies(true)[@project["company_uuid"]]
|
71
|
+
|
72
|
+
grand_total = @project["grand_total"]
|
73
|
+
grand_total += (Time.now.to_i - @project["started_at"]) if @project["running"]
|
74
|
+
overdue = grand_total > @project["time_limit"] if @project["time_limit"]
|
75
|
+
|
76
|
+
clock_string = to_clock_s(grand_total, true)
|
77
|
+
clock_string = " [#{HighLine::String.new(clock_string).red}]" if overdue
|
78
|
+
|
79
|
+
str = ""
|
80
|
+
if @options[:time]
|
81
|
+
str = clock_string
|
82
|
+
else
|
83
|
+
str += "#{company["name"]}: #{@project["name"]}"
|
84
|
+
str += " [#{clock_string}]"
|
85
|
+
str += " #{HighLine::String.new("Running").green}" if @project["running"]
|
86
|
+
end
|
87
|
+
|
88
|
+
print "\e[0K\r#{str}" if @options[:foreground]
|
89
|
+
print str unless @options[:foreground]
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_clock_s(time, show_seconds = false)
|
93
|
+
hour = (time.abs / 3600).floor
|
94
|
+
minute = (time.abs / 60 % 60).floor
|
95
|
+
seconds = (time.abs % 60).floor if show_seconds
|
96
|
+
|
97
|
+
return (time != 0 && (time / time.abs) == -1 ? "-" : "") + hour.to_s.rjust(2, '0') + ":" + minute.to_s.rjust(2, '0') + (show_seconds ? ":" + seconds.to_s.rjust(2, '0') : '')
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
module Commands
|
3
|
+
class Stop
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
def self.run!(settings)
|
7
|
+
options = Trollop::options do
|
8
|
+
banner <<-EOS
|
9
|
+
88 Miles Command line application - http://88miles.net
|
10
|
+
|
11
|
+
Punch out of the project.
|
12
|
+
|
13
|
+
Usage
|
14
|
+
88miles stop [options]
|
15
|
+
|
16
|
+
options:
|
17
|
+
EOS
|
18
|
+
opt :notes, "Save notes against the shift", :type => :string
|
19
|
+
opt :tags, "Allocate tags to the shift", :type => :string
|
20
|
+
end
|
21
|
+
|
22
|
+
instance = self.new(settings, options)
|
23
|
+
begin
|
24
|
+
return instance.punch_out
|
25
|
+
rescue OAuth2::Error => e
|
26
|
+
say "Access to your 88 Miles may have been revoked. Please run <%= color('88miles setup', BOLD) %> again."
|
27
|
+
return INVALID_OAUTH_TOKEN_EXIT_CODE
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(settings, options)
|
32
|
+
@settings = settings
|
33
|
+
@options = options
|
34
|
+
|
35
|
+
@access_key = OAuth.token(@settings.access_key)
|
36
|
+
@cache = Cache.new(settings, @access_key)
|
37
|
+
end
|
38
|
+
|
39
|
+
def punch_out
|
40
|
+
project = Gigawatt::ProjectFile.new.project
|
41
|
+
|
42
|
+
if project
|
43
|
+
response = JSON.parse(@access_key.post("/api/1/projects/#{project["uuid"]}/punch_out.json", { :params => { :notes => options.notes.to_s } }).body)
|
44
|
+
current = response["response"]
|
45
|
+
ProjectFile.write(current)
|
46
|
+
|
47
|
+
company = @cache.companies(true)[project["company_uuid"]]
|
48
|
+
say("Punched out of #{company["name"]}: #{project["name"]}")
|
49
|
+
return OK_EXIT_CODE
|
50
|
+
else
|
51
|
+
say("No project found. Did you remember to run <%= color('88miles init [directory]', BOLD) %>?")
|
52
|
+
return NO_PROJECT_EXIT_CODE
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
module Commands
|
3
|
+
class Sync
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
def self.run!(settings)
|
7
|
+
options = Trollop::options do
|
8
|
+
banner <<-EOS
|
9
|
+
88 Miles Command line application - http://88miles.net
|
10
|
+
|
11
|
+
88 Miles caches your company and project list to speed things up. Run this command if you add, edit or remove companies or projects
|
12
|
+
|
13
|
+
If run inside a directory with a linked project, the linked project will be updated too
|
14
|
+
|
15
|
+
Usage
|
16
|
+
88miles sync
|
17
|
+
EOS
|
18
|
+
end
|
19
|
+
|
20
|
+
instance = self.new(settings, options)
|
21
|
+
begin
|
22
|
+
instance.sync
|
23
|
+
instance.sync_current
|
24
|
+
rescue OAuth2::Error => e
|
25
|
+
say "Access to your 88 Miles may have been revoked. Please run <%= color('88miles setup', BOLD) %> again."
|
26
|
+
return INVALID_OAUTH_TOKEN_EXIT_CODE
|
27
|
+
end
|
28
|
+
|
29
|
+
return 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(settings, options)
|
33
|
+
@settings = settings
|
34
|
+
@options = options
|
35
|
+
|
36
|
+
@access_key = OAuth.token(@settings.access_key)
|
37
|
+
@cache = Cache.new(settings, @access_key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def sync
|
41
|
+
@cache.refresh!
|
42
|
+
end
|
43
|
+
|
44
|
+
def sync_current
|
45
|
+
project = Gigawatt::ProjectFile.new.project
|
46
|
+
if project
|
47
|
+
response = JSON.parse(@access_key.get("/api/1/projects/#{project["uuid"]}.json").body)
|
48
|
+
ProjectFile.write(response["response"])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
class OAuth
|
3
|
+
def self.client
|
4
|
+
if ENV['ENV'] == 'development'
|
5
|
+
client = OAuth2::Client.new('NjtVKz6Di3ccJjn2AGwZKhSxYBX4QHPJ5w1LrZOR', nil, :site => 'http://localhost:3000')
|
6
|
+
else
|
7
|
+
client = OAuth2::Client.new('hhWZrEF6YTlPUKrggiesnjXAFViLa8FBZNNUtr8L', nil, :site => 'https://88miles.net')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.token(token)
|
12
|
+
OAuth2::AccessToken.new(self.client, token)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.redirect_uri
|
16
|
+
if ENV['ENV'] == 'development'
|
17
|
+
"http://localhost:3000/oauth/authorized"
|
18
|
+
else
|
19
|
+
"https://88miles.net/oauth/authorized"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
class Options
|
3
|
+
SUB_COMMANDS = %w(setup init start stop sync status log)
|
4
|
+
|
5
|
+
def self.parse!
|
6
|
+
version_string = File.read(File.join(File.dirname(__FILE__), '..', '..', 'VERSION')).strip
|
7
|
+
|
8
|
+
options = Trollop::options do
|
9
|
+
version "88miles #{version_string}"
|
10
|
+
stop_on SUB_COMMANDS
|
11
|
+
banner <<-EOS
|
12
|
+
88 Miles Command line application - http://88miles.net
|
13
|
+
|
14
|
+
Usage:
|
15
|
+
88miles [globaloptions] <subcommand> [options]
|
16
|
+
|
17
|
+
subcommands:
|
18
|
+
setup: Link your 88 Miles account to this program
|
19
|
+
init: Link a project to a directory
|
20
|
+
start: Punch in to the linked project
|
21
|
+
stop: Punch out of the linked project
|
22
|
+
sync: Refresh the local cache from the server
|
23
|
+
status: Show the project timer
|
24
|
+
log: Print out the project shifts
|
25
|
+
|
26
|
+
globaloptions:
|
27
|
+
EOS
|
28
|
+
opt :settings, "Path to store 88 Miles settings", :default => Settings.defaults[:path], :type => :string
|
29
|
+
end
|
30
|
+
|
31
|
+
settings = Settings.new(options)
|
32
|
+
cmd = ARGV.shift.strip
|
33
|
+
case cmd
|
34
|
+
when "setup"
|
35
|
+
Gigawatt::Commands::Setup.run!(settings)
|
36
|
+
when "init"
|
37
|
+
Gigawatt::Commands::Init.run!(settings)
|
38
|
+
when "start"
|
39
|
+
Gigawatt::Commands::Start.run!(settings)
|
40
|
+
when "stop"
|
41
|
+
Gigawatt::Commands::Stop.run!(settings)
|
42
|
+
when "sync"
|
43
|
+
Gigawatt::Commands::Sync.run!(settings)
|
44
|
+
when "status"
|
45
|
+
Gigawatt::Commands::Status.run!(settings)
|
46
|
+
when "log"
|
47
|
+
Gigawatt::Commands::Log.run!(settings)
|
48
|
+
else
|
49
|
+
Trollop::die "Unknown subcommand #{cmd.inspect}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
class ProjectFile
|
3
|
+
def find_the_dotfile(dir = Dir.pwd)
|
4
|
+
file = File.join(dir, ProjectFile.filename)
|
5
|
+
if File.exists?(file)
|
6
|
+
return File.join(file)
|
7
|
+
else
|
8
|
+
parts = dir.split(File::SEPARATOR)[0..-2]
|
9
|
+
if parts.length == 0
|
10
|
+
return nil
|
11
|
+
else
|
12
|
+
return find_the_dotfile(File.join(parts))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def project
|
18
|
+
dotfile = find_the_dotfile
|
19
|
+
if dotfile
|
20
|
+
YAML.load_file(dotfile)
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.write(project)
|
27
|
+
File.write(File.join(Dir.pwd, ProjectFile.filename), project.to_hash.to_yaml)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.filename
|
31
|
+
".88miles"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Gigawatt
|
2
|
+
class Settings
|
3
|
+
attr_accessor :access_key, :projects, :companies, :staff
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@options = Settings.defaults.merge(options)
|
7
|
+
read if setup?
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.defaults
|
11
|
+
{
|
12
|
+
:path => File.join(Dir.home, '.88miles')
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup?
|
17
|
+
File.exists?(path) && File.directory?(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def path
|
21
|
+
@options[:path]
|
22
|
+
end
|
23
|
+
|
24
|
+
def read
|
25
|
+
self.access_key = YAML.load_file(File.join(path, 'accesskey')) if File.exists?(File.join(path, 'accesskey'))
|
26
|
+
self.companies = YAML.load_file(File.join(path, 'companies')) if File.exists?(File.join(path, 'companies'))
|
27
|
+
self.projects = YAML.load_file(File.join(path, 'projects')) if File.exists?(File.join(path, 'projects'))
|
28
|
+
self.staff = YAML.load_file(File.join(path, 'staff')) if File.exists?(File.join(path, 'staff'))
|
29
|
+
end
|
30
|
+
|
31
|
+
def write(type)
|
32
|
+
# Make the directory if it doesn't exist
|
33
|
+
FileUtils.mkdir_p(path) unless File.exists?(path)
|
34
|
+
File.write(File.join(path, 'accesskey'), self.access_key.to_yaml) if type == :accesskey
|
35
|
+
File.write(File.join(path, 'companies'), self.companies.to_yaml) if type == :companies
|
36
|
+
File.write(File.join(path, 'projects'), self.projects.to_yaml) if type == :projects
|
37
|
+
File.write(File.join(path, 'staff'), self.staff.to_yaml) if type == :staff
|
38
|
+
FileUtils.chmod 0700, path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/gigawatt.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
require 'highline/import'
|
3
|
+
require 'oauth2'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'json'
|
6
|
+
require 'open-uri'
|
7
|
+
require 'terminal-table'
|
8
|
+
require 'launchy'
|
9
|
+
|
10
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'cache')
|
11
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'settings')
|
12
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'project_file')
|
13
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'application')
|
14
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'oauth')
|
15
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'options')
|
16
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'commands', 'setup')
|
17
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'commands', 'init')
|
18
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'commands', 'start')
|
19
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'commands', 'stop')
|
20
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'commands', 'sync')
|
21
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'commands', 'status')
|
22
|
+
require File.join(File.dirname(__FILE__), 'gigawatt', 'commands', 'log')
|
23
|
+
|
24
|
+
module Gigawatt
|
25
|
+
NO_PROJECT_EXIT_CODE = 3
|
26
|
+
SETTINGS_FILE_EXISTS = 2
|
27
|
+
INVALID_OAUTH_TOKEN_EXIT_CODE = 1
|
28
|
+
OK_EXIT_CODE = 0
|
29
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'gigawatt'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|