lhbackup 0.1.0

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,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.sublime-project
19
+ *.sublime-workspace
20
+ .DS_Store
21
+ run
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lhbackup.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Nathan Youngman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ # Lhbackup
2
+
3
+ On-demand backup of Lighthouse.
4
+
5
+ ## Installation
6
+
7
+ Install it:
8
+
9
+ $ gem install lhbackup
10
+
11
+ ## Usage
12
+
13
+ Run it:
14
+
15
+ $ lhbackup --help
16
+
17
+ --account, -a <s>: Lighthouse account (eg. activereload)
18
+ --token, -t <s>: Token to authenticate with
19
+ --output, -o <s>: Output folder (defaults to account)
20
+
21
+ ## Contributing
22
+
23
+ 1. Fork it
24
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
25
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
26
+ 4. Push to the branch (`git push origin my-new-feature`)
27
+ 5. Create new Pull Request
28
+
29
+ ## TODO
30
+
31
+ * Tags, skipped as was running into errors with the Lighthouse gem.
32
+ * Other users that aren't currently members of a project? (are they still in Lighthouse anyway?)
33
+ * Message attachments are not downloaded
34
+ * Individual requests contain more information (ticket versions), which are not retrieved.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+
6
+ Bundler.setup :default
7
+ Bundler.require :default
8
+
9
+ require 'lhbackup'
10
+ Lhbackup::main
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/lhbackup/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Nathan Youngman"]
6
+ gem.email = ["git@nathany.com"]
7
+ gem.description = %q{On-demand backup of Lighthouse.}
8
+ gem.summary = %q{For some reason the Lighthouse project export feature never seems to work for me.}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "lhbackup"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Lhbackup::VERSION
17
+
18
+ gem.add_runtime_dependency('lighthouse', '~> 2.1')
19
+ gem.add_runtime_dependency('addressable', '~> 2.2')
20
+ gem.add_runtime_dependency('trollop', '~> 1.16')
21
+ end
@@ -0,0 +1,4 @@
1
+ require "lhbackup/version"
2
+ require "lhbackup/cli"
3
+ require "lhbackup/backup"
4
+
@@ -0,0 +1,127 @@
1
+ # Lighthouse
2
+ # http://lighthouseapp.com/api/
3
+ # https://github.com/smathy/lighthouse
4
+ require 'lighthouse'
5
+ require 'set'
6
+
7
+ module Lhbackup
8
+
9
+ class Backup
10
+ def initialize(account, token)
11
+ Lighthouse.account = account
12
+ Lighthouse.token = token
13
+ end
14
+
15
+ def run
16
+ print "Retreiving projects..."
17
+ projects = Lighthouse::Project.find(:all)
18
+ store(projects, 'projects.json')
19
+
20
+ projects.each do |project|
21
+ puts "#{project.permalink}:"
22
+ retrieve_project(project)
23
+ end
24
+ end
25
+
26
+ def retrieve_project(project)
27
+ @project = project
28
+ @attachments = Set.new
29
+
30
+ # subfolder for the project
31
+ @folder = File.join(FileUtils.pwd, @project.permalink)
32
+
33
+ # unpaginated resources
34
+ retrieve_resource "memberships"
35
+ retrieve_resource "bins"
36
+
37
+ # paginated resources
38
+ %w{milestones tickets messages changesets}.each do |resource|
39
+ retrieve_resource resource, :paginated
40
+ end
41
+
42
+ # attachments
43
+ puts "#{@attachments.count} attachments to download"
44
+
45
+ File.open(File.join(@folder, "attachments.sh"), "w") do |f|
46
+ f.write(@attachments.map {|url| curl(url)}.join("\n"))
47
+ end
48
+ system(File.join(@folder, "attachments.sh"))
49
+ end
50
+
51
+ def retrieve_resource(resource, paginated = false)
52
+ print "- retreiving #{resource}"
53
+
54
+ data = if paginated
55
+ load_pages do |p|
56
+ @project.send(resource, :page => p)
57
+ end
58
+ else
59
+ @project.send(resource)
60
+ puts
61
+ end
62
+
63
+ store(data, File.join(@folder, "#{resource}.json"))
64
+
65
+ find_attachments(data) if resource == "tickets"
66
+ # TODO: messages have attachments too (but on the comments)
67
+ end
68
+
69
+ def find_attachments(data)
70
+ print "- finding #{data.sum(&:attachments_count)} attachments"
71
+
72
+ attachment_data = data.map do |obj|
73
+ next if obj.attachments_count.zero?
74
+
75
+ # individual tickets respond to attachments, but the listed ones don't
76
+ attachments = Lighthouse::Ticket.find(obj.number, :params => {:project_id => @project.id}).attachments
77
+ putc '.'
78
+
79
+ attachments.each do |a|
80
+ if a.respond_to?(:url)
81
+ @attachments << a.url
82
+ elsif a.respond_to?(:image) && a.image.respond_to?(:url)
83
+ @attachments << a.image.url
84
+ else
85
+ puts "Whats the url for this attachment? #{a.to_json}"
86
+ end
87
+ end
88
+ {obj.number => attachments} # ticket to attachments
89
+ end.compact
90
+
91
+ store(attachment_data, File.join(@folder, "ticket-attachments.json"))
92
+ end
93
+
94
+ def curl(url)
95
+ output = File.join(@folder, URI(url).path)
96
+ "curl -H 'X-LighthouseToken: #{Lighthouse.token}' #{url} -o #{output} -L --create-dirs"
97
+ # -C - would continue downloads
98
+ end
99
+
100
+ def store(data, file)
101
+ FileUtils.mkdir_p(File.dirname(file)) if File.dirname(file).present?
102
+
103
+ puts " saving #{File.basename(file)}"
104
+
105
+ File.open(file, "w") do |f|
106
+ f.write(data.to_json)
107
+ end
108
+ end
109
+
110
+ # results are paginated, get them all
111
+ def load_pages
112
+ p = 1
113
+ results = []
114
+ while true
115
+ result = yield p
116
+ # TODO error cases
117
+ break if result.count.zero?
118
+ results += result
119
+ p = p + 1
120
+ putc "."
121
+ end
122
+ puts
123
+ results
124
+ end
125
+ end
126
+
127
+ end
@@ -0,0 +1,24 @@
1
+ # Trollop
2
+ # http://trollop.rubyforge.org/
3
+ # http://rubydoc.info/gems/trollop/1.16.2/Trollop/Parser
4
+ require 'trollop'
5
+
6
+ module Lhbackup
7
+
8
+ def self.main
9
+ opts = Trollop::options do
10
+ version "lhbackup #{VERSION} Copyright (c) 2012 Nathan Youngman"
11
+ banner "Lighthouse Backup"
12
+ opt :account, "Lighthouse account (eg. activereload)", :type => :string, :required => true
13
+ opt :token, "Token to authenticate with", :type => :string, :required => true
14
+ opt :output, "Output folder (defaults to account)", :type => :string
15
+ end
16
+
17
+ folder = opts[:output] || opts[:account]
18
+ FileUtils.mkdir_p(folder)
19
+ FileUtils.chdir(folder)
20
+
21
+ Backup.new(opts[:account], opts[:token]).run
22
+ end
23
+
24
+ end
@@ -0,0 +1,3 @@
1
+ module Lhbackup
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lhbackup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nathan Youngman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: lighthouse
16
+ requirement: &70148192233640 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70148192233640
25
+ - !ruby/object:Gem::Dependency
26
+ name: addressable
27
+ requirement: &70148192233100 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '2.2'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70148192233100
36
+ - !ruby/object:Gem::Dependency
37
+ name: trollop
38
+ requirement: &70148192232320 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '1.16'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70148192232320
47
+ description: On-demand backup of Lighthouse.
48
+ email:
49
+ - git@nathany.com
50
+ executables:
51
+ - lhbackup
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - .gitignore
56
+ - Gemfile
57
+ - LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - bin/lhbackup
61
+ - lhbackup.gemspec
62
+ - lib/lhbackup.rb
63
+ - lib/lhbackup/backup.rb
64
+ - lib/lhbackup/cli.rb
65
+ - lib/lhbackup/version.rb
66
+ homepage: ''
67
+ licenses: []
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ segments:
79
+ - 0
80
+ hash: 2739751983264181991
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ segments:
88
+ - 0
89
+ hash: 2739751983264181991
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 1.8.15
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: For some reason the Lighthouse project export feature never seems to work
96
+ for me.
97
+ test_files: []