stencil 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2009 Winton Welsh
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,4 @@
1
+ Stencil
2
+ =======
3
+
4
+ Project template manager.
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/gempackagetask'
4
+ require 'spec/rake/spectask'
5
+ require 'gemspec'
6
+
7
+ desc "Generate gemspec"
8
+ task :gemspec do
9
+ File.open("#{Dir.pwd}/#{GEM_NAME}.gemspec", 'w') do |f|
10
+ f.write(GEM_SPEC.to_ruby)
11
+ end
12
+ end
13
+
14
+ desc "Install gem"
15
+ task :install do
16
+ Rake::Task['gem'].invoke
17
+ `sudo gem uninstall #{GEM_NAME} -x`
18
+ `sudo gem install pkg/#{GEM_NAME}*.gem`
19
+ `rm -Rf pkg`
20
+ end
21
+
22
+ desc "Package gem"
23
+ Rake::GemPackageTask.new(GEM_SPEC) do |pkg|
24
+ pkg.gem_spec = GEM_SPEC
25
+ end
26
+
27
+ desc "Run specs"
28
+ Spec::Rake::SpecTask.new do |t|
29
+ t.rcov = true
30
+ t.spec_opts = ["--format", "specdoc", "--colour"]
31
+ t.spec_files = FileList["spec/**/*_spec.rb"]
32
+ end
data/bin/stencil ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.push File.expand_path("#{File.dirname(__FILE__)}/../lib")
4
+ require 'stencil'
5
+
6
+ Stencil.new(ARGV)
data/gemspec.rb ADDED
@@ -0,0 +1,19 @@
1
+ GEM_NAME = 'stencil'
2
+ GEM_FILES = FileList['**/*'] - FileList['coverage', 'coverage/**/*', 'pkg', 'pkg/**/*']
3
+ GEM_SPEC = Gem::Specification.new do |s|
4
+ # == CONFIGURE ==
5
+ s.author = "Winton Welsh"
6
+ s.email = "mail@wintoni.us"
7
+ s.homepage = "http://github.com/winton/#{GEM_NAME}"
8
+ s.summary = "Project template manager"
9
+ # == CONFIGURE ==
10
+ s.add_dependency('httparty', '=0.4.5')
11
+ s.executables << GEM_NAME
12
+ s.extra_rdoc_files = [ "README.markdown" ]
13
+ s.files = GEM_FILES.to_a
14
+ s.has_rdoc = false
15
+ s.name = GEM_NAME
16
+ s.platform = Gem::Platform::RUBY
17
+ s.require_path = "lib"
18
+ s.version = "0.1.0"
19
+ end
data/lib/stencil.rb ADDED
@@ -0,0 +1,48 @@
1
+ Dir["#{File.dirname(__FILE__)}/stencil/*.rb"].each do |path|
2
+ require path
3
+ end
4
+
5
+ class Stencil
6
+
7
+ def initialize(args)
8
+ @path = Dir.pwd
9
+ @name = File.basename(@path).intern
10
+
11
+ # If template, do a template merge
12
+ if Config.exists?(:templates, @path)
13
+ Merge.template(@path)
14
+
15
+ # If project
16
+ elsif Config.exists?(:projects, @path)
17
+
18
+ # If upstream commit, merge upstream
19
+ if args.first('<')
20
+ Merge.upstream args[1..-1]
21
+
22
+ # If template specified, update config
23
+ elsif args.first
24
+ Config.update(:projects => {
25
+ @name => {
26
+ :template => template,
27
+ :branches => branches
28
+ }
29
+ })
30
+
31
+ # Do a project merge
32
+ Merge.project(@path)
33
+
34
+ # If not configured
35
+ else
36
+
37
+ # Update config
38
+ Msg.is_template_or_project?(@name)
39
+ Config.update((STDIN.gets[0..0].downcase == 't' ? :templates : :projects) => {
40
+ @name => { :path => @path }
41
+ })
42
+
43
+ # Re-run
44
+ initialize args
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + "/cmd"
2
+
3
+ class Stencil
4
+ class Branches
5
+ class <<self
6
+
7
+ def read(path)
8
+ branches = Cmd.run path, 'git branch'
9
+ branches = branches.split(/\s+/)
10
+ branches.delete '*'
11
+ branches.delete 'master'
12
+ branches
13
+ end
14
+
15
+ def grouped(path)
16
+ groups, ignore = [], []
17
+ branches = read(path).sort { |a, b| a.length <=> b.length }
18
+ branches.each do |branch|
19
+ next if ignore.include?(branch)
20
+ groups << [ branch ] + group(branches, branch)
21
+ ignore += groups.last
22
+ end
23
+ groups
24
+ end
25
+
26
+ private
27
+
28
+ def group(branches, branch)
29
+ branches.select do |b|
30
+ b != branch && b[0..branch.length-1] == branch
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ class Stencil
2
+ class Cmd
3
+ class <<self
4
+
5
+ def run(path, cmd=nil)
6
+ if cmd.nil?
7
+ cmd, path = path, cmd
8
+ else
9
+ path = "cd #{path} && "
10
+ end
11
+ `#{[ path, cmd ].compact.join}`
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ require 'yaml'
2
+
3
+ class Stencil
4
+ class Config
5
+ class <<self
6
+
7
+ @@cache = nil
8
+ @@path = File.expand_path('~/.stencil.yml')
9
+
10
+ def create
11
+ write(:projects => {}, :templates => {})
12
+ end
13
+
14
+ def read
15
+ if @@cache
16
+ @@cache
17
+ elsif File.exists?(@@path)
18
+ File.open(@@path, 'r') do |f|
19
+ @@cache = YAML::load f
20
+ end
21
+ else
22
+ create
23
+ @@cache = read
24
+ end
25
+ end
26
+
27
+ def update(hash)
28
+ write read.deep_merge(hash)
29
+ end
30
+
31
+ def delete
32
+ @@cache = nil
33
+ File.unlink @@path
34
+ end
35
+
36
+ def exists?(type, name)
37
+ read[type] &&
38
+ (
39
+ read[type][name.intern] ||
40
+ (
41
+ read[type][File.basename(name).intern] &&
42
+ read[type][File.basename(name).intern][:path] == name
43
+ )
44
+ )
45
+ end
46
+
47
+ private
48
+
49
+ def write(hash)
50
+ @@cache = nil
51
+ File.open(@@path, 'w') do |f|
52
+ f.write YAML::dump(hash)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,6 @@
1
+ class Hash
2
+ def deep_merge(second)
3
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
4
+ self.merge(second, &merger)
5
+ end
6
+ end
@@ -0,0 +1,55 @@
1
+ class Stencil
2
+ class Merge
3
+ class <<self
4
+
5
+ def project(path)
6
+ template = Config.read[:projects][@name][:template]
7
+ branches = Config.read[:projects][@name][:branches]
8
+ if template
9
+ template = Config.read[:templates][template.intern]
10
+ if template && File.exists?(template[:path])
11
+ origin = Cmd.run template[:path], "git remote show origin"
12
+ origin = origin.match(/URL:\s+(\S+)/)[1]
13
+ Msg.template_url origin
14
+ Cmd.run path, "git remote rm template"
15
+ Cmd.run path, "git remote add template #{origin}"
16
+ branches = %w(master) if branches.empty?
17
+ branches.each do |branch|
18
+ Msg.merge_remote_branch branch
19
+ Cmd.run path, "git pull template #{branch}"
20
+ end
21
+ else
22
+ Msg.template_not_found template
23
+ Msg.specify_template
24
+ end
25
+ else
26
+ Msg.specify_template
27
+ end
28
+ end
29
+
30
+ def template(path)
31
+ Branches.grouped(path).each do |branches|
32
+ branches.unshift('master')
33
+ progressive(path, branches)
34
+ end
35
+ Cmd.run path, "git checkout master"
36
+ end
37
+
38
+ private
39
+
40
+ def progressive(path, branches)
41
+ merger = branches.shift
42
+ mergee = branches.first
43
+ if merger && mergee
44
+ puts "Merging \"#{merger}\" into \"#{mergee}\""
45
+ output = Cmd.run(path, "git checkout #{mergee} && git merge #{merger}")
46
+ if output.downcase.include?('conflict')
47
+ puts output
48
+ else
49
+ progressive(path, branches)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,27 @@
1
+ class Stencil
2
+ class Msg
3
+ class <<self
4
+
5
+ def is_template_or_project?(name)
6
+ puts "Is \"#{name}\" a template or a project?"
7
+ end
8
+
9
+ def merge_remote_branch(branch)
10
+ puts "Merging remote branch \"#{branch}\""
11
+ end
12
+
13
+ def specify_template
14
+ puts "Please tell stencil what template you want to receive updates from:"
15
+ puts " stencil TEMPLATE [BRANCH BRANCH ...]"
16
+ end
17
+
18
+ def template_not_found(template)
19
+ puts "Template \"#{template}\" not found."
20
+ end
21
+
22
+ def template_url(url)
23
+ puts "Found template URL: #{url}"
24
+ end
25
+ end
26
+ end
27
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,16 @@
1
+ $TESTING=true
2
+ SPEC = File.dirname(__FILE__)
3
+ $:.unshift File.expand_path("#{SPEC}/../lib")
4
+
5
+ require 'stencil'
6
+ require 'pp'
7
+
8
+ Spec::Runner.configure do |config|
9
+ end
10
+
11
+ # For use with rspec textmate bundle
12
+ def debug(object)
13
+ puts "<pre>"
14
+ puts object.pretty_inspect.gsub('<', '&lt;').gsub('>', '&gt;')
15
+ puts "</pre>"
16
+ end
data/stencil.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{stencil}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Winton Welsh"]
9
+ s.date = %q{2009-11-06}
10
+ s.default_executable = %q{stencil}
11
+ s.email = %q{mail@wintoni.us}
12
+ s.executables = ["stencil"]
13
+ s.extra_rdoc_files = ["README.markdown"]
14
+ s.files = ["bin", "bin/stencil", "gemspec.rb", "lib", "lib/stencil", "lib/stencil/branches.rb", "lib/stencil/cmd.rb", "lib/stencil/config.rb", "lib/stencil/hash.rb", "lib/stencil/merge.rb", "lib/stencil/msg.rb", "lib/stencil.rb", "MIT-LICENSE", "Rakefile", "README.markdown", "spec", "spec/spec.opts", "spec/spec_helper.rb"]
15
+ s.homepage = %q{http://github.com/winton/stencil}
16
+ s.require_paths = ["lib"]
17
+ s.rubygems_version = %q{1.3.5}
18
+ s.summary = %q{Project template manager}
19
+
20
+ if s.respond_to? :specification_version then
21
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
22
+ s.specification_version = 3
23
+
24
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
25
+ s.add_runtime_dependency(%q<httparty>, ["= 0.4.5"])
26
+ else
27
+ s.add_dependency(%q<httparty>, ["= 0.4.5"])
28
+ end
29
+ else
30
+ s.add_dependency(%q<httparty>, ["= 0.4.5"])
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stencil
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Winton Welsh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-06 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - "="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.5
24
+ version:
25
+ description:
26
+ email: mail@wintoni.us
27
+ executables:
28
+ - stencil
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.markdown
33
+ files:
34
+ - bin/stencil
35
+ - gemspec.rb
36
+ - lib/stencil/branches.rb
37
+ - lib/stencil/cmd.rb
38
+ - lib/stencil/config.rb
39
+ - lib/stencil/hash.rb
40
+ - lib/stencil/merge.rb
41
+ - lib/stencil/msg.rb
42
+ - lib/stencil.rb
43
+ - MIT-LICENSE
44
+ - Rakefile
45
+ - README.markdown
46
+ - spec/spec.opts
47
+ - spec/spec_helper.rb
48
+ - stencil.gemspec
49
+ has_rdoc: true
50
+ homepage: http://github.com/winton/stencil
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Project template manager
77
+ test_files: []
78
+