fwtoolkit 0.9.3 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/bin/fwt +2 -112
- data/features/cocoapods/setup.feature +60 -0
- data/features/frank/model.feature +20 -0
- data/features/frank/setup.feature +28 -0
- data/features/git/create.feature +29 -0
- data/features/project/create.feature +25 -0
- data/features/step_definitions/aruba_steps.rb +11 -0
- data/features/step_definitions/git_steps.rb +30 -0
- data/features/step_definitions/project_steps.rb +50 -0
- data/features/step_definitions/rvm_steps.rb +11 -0
- data/features/step_definitions/system_steps.rb +8 -0
- data/features/support/env.rb +23 -0
- data/features/support/lib_test/aruba_fwt.rb +30 -0
- data/features/support/lib_test/aruba_mod.rb +28 -0
- data/features/support/lib_test/fake_gem.rb +47 -0
- data/features/xcode/create.feature +42 -0
- data/lib/fwtoolkit/cli/bootstrap.rb +75 -0
- data/lib/fwtoolkit/cli/ci.rb +52 -0
- data/lib/fwtoolkit/cli/cocoapods.rb +73 -0
- data/lib/fwtoolkit/cli/ext/thor.rb +35 -0
- data/lib/fwtoolkit/cli/frank.rb +113 -0
- data/lib/fwtoolkit/cli/fw_actions/template_dir.rb +59 -0
- data/lib/fwtoolkit/cli/fw_actions.rb +2 -0
- data/lib/fwtoolkit/cli/git.rb +42 -0
- data/lib/fwtoolkit/cli/ota.rb +109 -0
- data/lib/fwtoolkit/cli/ota_client/hockeyapp_client.rb +70 -0
- data/lib/fwtoolkit/cli/project.rb +83 -0
- data/lib/fwtoolkit/cli/thorutils.rb +14 -0
- data/lib/fwtoolkit/cli/xcode.rb +105 -0
- data/lib/fwtoolkit/cli.rb +27 -36
- data/lib/fwtoolkit/config/config.sample +8 -0
- data/lib/fwtoolkit/config.rb +41 -0
- data/lib/fwtoolkit/configfile.rb +36 -0
- data/lib/fwtoolkit/executable/executable.rb +45 -0
- data/lib/fwtoolkit/executable.rb +1 -0
- data/lib/fwtoolkit/ext/gem.rb +9 -0
- data/lib/fwtoolkit/ext/hash_yaml.rb +17 -0
- data/lib/fwtoolkit/git_client/git_client.rb +225 -0
- data/lib/fwtoolkit/git_client.rb +1 -0
- data/lib/fwtoolkit/projectfile.rb +50 -0
- data/lib/fwtoolkit/rake/ext/rake.rb +7 -0
- data/lib/fwtoolkit/rake/tasks/ci.rb +25 -0
- data/lib/fwtoolkit/rake/tasks/config.rb +13 -0
- data/lib/fwtoolkit/rake/tasks/ota.rb +31 -0
- data/lib/fwtoolkit/rake/tasks/project.rb +28 -0
- data/lib/fwtoolkit/rake/tasks/test.rb +59 -0
- data/lib/fwtoolkit/rake/tasks/xcode.rb +69 -0
- data/lib/fwtoolkit/rake/tasks.rb +20 -0
- data/lib/fwtoolkit/version.rb +1 -1
- data/lib/fwtoolkit.rb +4 -7
- data/spec/git_client_spec.rb +316 -0
- data/spec/project_config_spec.rb +40 -0
- data/spec/rake/project.rb +28 -0
- data/spec/rake/test.rb +85 -0
- data/spec/rake/xcode.rb +66 -0
- data/spec/support/aruba-doubles-rspec.rb +21 -0
- data/spec/support/ctx_rake.rb +23 -0
- data/spec/support/double_helper.rb +13 -0
- data/spec/support/project_generator.rb +45 -0
- data/templates/default_project/frank/%project_name%/%target_name%/%class_prefix%AppDelegate+Frank.h.tt +15 -0
- data/templates/{cucumber/AppDelegate+Frank.m.erb → default_project/frank/%project_name%/%target_name%/%class_prefix%AppDelegate+Frank.m.tt} +25 -21
- data/templates/{cucumber → default_project/frank/%project_name%/Frank}/features/example.feature +0 -0
- data/templates/{cucumber → default_project/frank/%project_name%/Frank}/features/step_definitions/launch_steps.rb +0 -0
- data/templates/{cucumber → default_project/frank/%project_name%/Frank}/features/support/env.rb +0 -0
- data/templates/{cucumber → default_project/frank/%project_name%/Frank}/features/support/mimic.rb +0 -0
- data/templates/default_project/frank/~template_config.rb +11 -0
- data/templates/default_project/frank_seed_core_data/%project_name%/Frank/features/support/models/%class_name%.rb.tt +30 -0
- data/templates/default_project/frank_seed_support/%project_name%/Frank/features/support/models/factories.rb.tt +10 -0
- data/templates/{cucumber → default_project/frank_seed_support/%project_name%/Frank}/features/support/views/my_objects_json.erb +0 -0
- data/templates/{cucumber → default_project/frank_seed_support/%project_name%/Frank}/features/support/views/my_objects_xml.erb +0 -0
- data/templates/{fwt/gitignore.erb → default_project/git/.gitignore} +0 -0
- data/templates/{fwt/rvmrc.erb → default_project/rvm/.rvmrc.tt} +2 -2
- data/templates/default_project/rvm/Gemfile +4 -0
- data/templates/default_project/xcode/%project_name%/%project_name%.xcodeproj/project.pbxproj.tt +583 -0
- data/templates/default_project/xcode/%project_name%/%project_name%.xcodeproj/project.xcworkspace/contents.xcworkspacedata.tt +7 -0
- data/templates/default_project/xcode/%project_name%/%project_name%.xcodeproj/xcshareddata/xcschemes/%project_name%-Release.xcscheme.tt +105 -0
- data/templates/default_project/xcode/%project_name%/%project_name%.xcodeproj/xcshareddata/xcschemes/%project_name%-Testing.xcscheme.tt +105 -0
- data/templates/default_project/xcode/%project_name%/%project_name%.xcodeproj/xcshareddata/xcschemes/%project_name%.xcscheme.tt +105 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/%class_prefix%AppDelegate.h.tt +15 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/%class_prefix%AppDelegate.m.tt +49 -0
- data/templates/{fwt/default_project/Info.plist.erb → default_project/xcode/%project_name%/%target_name%/Supporting Files/%project_name%-Info.plist} +0 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/%project_name%-Prefix.pch.tt +14 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/Settings.bundle/Root.plist +53 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/Settings.bundle/en.lproj/Root.strings +0 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/en.lproj/InfoPlist.strings +2 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/fw-shared.xcconfig +49 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/info.plist.h.tt +8 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/main.m.tt +18 -0
- data/templates/default_project/xcode/%project_name%/%target_name%/Supporting Files/version.sh +159 -0
- data/templates/default_project/xcode/%project_name%/%tests_target_name%/%project_name%Tests.h.tt +13 -0
- data/templates/default_project/xcode/%project_name%/%tests_target_name%/%project_name%Tests.m.tt +32 -0
- data/templates/default_project/xcode/%project_name%/%tests_target_name%/Supporting Files/%tests_target_name%-Info.plist +22 -0
- data/templates/default_project/xcode/%project_name%/%tests_target_name%/Supporting Files/en.lproj/InfoPlist.strings +2 -0
- data/templates/default_project/xcode/%project_name%/Default.png +0 -0
- data/templates/default_project/xcode/%project_name%/Resources/Default-568h@2x.png +0 -0
- data/templates/default_project/xcode/%project_name%/Resources/Default.png +0 -0
- data/templates/default_project/xcode/%project_name%/Resources/Default@2x.png +0 -0
- data/templates/default_project/xcode/%project_name%.xcworkspace/contents.xcworkspacedata.tt +7 -0
- data/templates/default_project/xcode/FWProjectfile.tt +14 -0
- data/templates/default_project/xcode/Podfile.tt +4 -0
- data/templates/default_project/xcode/Rakefile.tt +14 -0
- data/templates/default_project/xcode/cruise_config.rb +3 -0
- data/templates/default_project/xcode/~template_config.rb +5 -0
- metadata +187 -141
- data/lib/fwtoolkit/tasks/build.rb +0 -121
- data/lib/fwtoolkit/tasks/ci.rb +0 -30
- data/lib/fwtoolkit/tasks/cocoapods.rb +0 -32
- data/lib/fwtoolkit/tasks/frank.rb +0 -119
- data/lib/fwtoolkit/tasks/helper.rb +0 -16
- data/lib/fwtoolkit/tasks/services.rb +0 -41
- data/lib/fwtoolkit/tasks.rb +0 -24
- data/lib/fwtoolkit/test/frank_model.rb +0 -120
- data/lib/fwtoolkit/test/misc_steps.rb +0 -9
- data/lib/fwtoolkit/test/model_helper.rb +0 -94
- data/lib/fwtoolkit/test/network_steps.rb +0 -60
- data/lib/fwtoolkit/test/pickle_steps.rb +0 -101
- data/lib/fwtoolkit/test/timeout_helper.rb +0 -21
- data/lib/fwtoolkit/test/ui_helper.rb +0 -19
- data/lib/fwtoolkit/test/ui_steps.rb +0 -17
- data/templates/cucumber/AppDelegate+Frank.h.erb +0 -15
- data/templates/fwt/Gemfile.erb +0 -3
- data/templates/fwt/Podfile.erb +0 -4
- data/templates/fwt/Rakefile.erb +0 -24
- data/templates/fwt/default_project/AppDelegate.h.erb +0 -12
- data/templates/fwt/default_project/AppDelegate.m.erb +0 -20
- data/templates/fwt/default_project/Prefix.pch.erb +0 -6
- data/templates/fwt/default_project/main.m.erb +0 -15
- data/templates/models/factories.rb.erb +0 -10
- data/templates/models/model.rb.erb +0 -30
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'fwtoolkit/cli/xcode'
|
3
|
+
require 'fwtoolkit/cli/cocoapods'
|
4
|
+
require 'fwtoolkit/cli/git'
|
5
|
+
require 'fwtoolkit/projectfile'
|
6
|
+
require 'fwtoolkit/git_client'
|
7
|
+
require 'fwtoolkit/cli/thorutils'
|
8
|
+
|
9
|
+
module FWToolkit
|
10
|
+
class Project < Thor
|
11
|
+
include Thor::Actions
|
12
|
+
|
13
|
+
include FWToolkit::ThorUtils
|
14
|
+
source_root_templates!
|
15
|
+
|
16
|
+
desc "new [PROJECT NAME] [CLASS PREFIX]", "Create a new Xcode project with FW's settings"
|
17
|
+
def new(project_name, class_prefix)
|
18
|
+
destination_root = File.join(Dir.pwd, project_name)
|
19
|
+
|
20
|
+
say "Creating new project in: #{File.expand_path destination_root}"
|
21
|
+
|
22
|
+
invoke :conf_rvm, [destination_root]
|
23
|
+
|
24
|
+
invoke FWToolkit::Xcode, 'new', [project_name, class_prefix.upcase, File.join(Dir.pwd, project_name)]
|
25
|
+
|
26
|
+
#invoke FWToolkit::Cocoapods, 'setup', [] #needs empty arg list or it will propagate father'
|
27
|
+
invoke FWToolkit::Cocoapods, 'install', [destination_root]
|
28
|
+
|
29
|
+
#invoke FWToolkit::Frank, 'setup', [destination_root, project_name, class_prefix.upcase]
|
30
|
+
|
31
|
+
git_repo = GitClient::Repository.new destination_root
|
32
|
+
# gitignore is included on xcode new.. for now
|
33
|
+
|
34
|
+
if(git_repo.initialized?)
|
35
|
+
say_status :skip, 'The git repository is already initialized', :yellow
|
36
|
+
else
|
37
|
+
invoke FWToolkit::Git, 'new', [destination_root]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "conf_rvm [PROJECT_DIR]", "Configure rvm/gem environment on a project's folder"
|
42
|
+
def conf_rvm(project_root=Dir.pwd)
|
43
|
+
@project_name = File.basename(project_root)
|
44
|
+
@ruby_version = Config.ruby_version
|
45
|
+
destination_root = project_root
|
46
|
+
|
47
|
+
say 'Configuring rvm'
|
48
|
+
|
49
|
+
directory 'templates/default_project/rvm', destination_root
|
50
|
+
|
51
|
+
inside(destination_root) do
|
52
|
+
run! "rvm #{Config.ruby_version} do rvm --rvmrc --create ruby-#{Config.ruby_version}@#{@project_name}", {:capture => true}
|
53
|
+
bundle_update
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "update [PROJECT_DIR]", "Update project's pods/gems and submodules"
|
58
|
+
def update(project_root=Dir.pwd)
|
59
|
+
bundle_update
|
60
|
+
|
61
|
+
invoke FWToolkit::Git, 'update', [project_root]
|
62
|
+
invoke FWToolkit::Cocoapods, 'install', [project_root]
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def bundle_update
|
69
|
+
if File.exists? 'Gemfile'
|
70
|
+
begin
|
71
|
+
retried ||= false
|
72
|
+
run! 'bundle'
|
73
|
+
rescue Thor::Error
|
74
|
+
run! 'gem install bundler'
|
75
|
+
retried = true
|
76
|
+
retry unless retried
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'fwtoolkit/config'
|
4
|
+
require 'fwtoolkit/projectfile'
|
5
|
+
require 'fwtoolkit/cli/fw_actions'
|
6
|
+
require 'fwtoolkit/cli/thorutils'
|
7
|
+
require 'xcodebuild'
|
8
|
+
|
9
|
+
# This little hack is necesary to use XcodeBuild outside the context of rake
|
10
|
+
module XcodeBuild
|
11
|
+
module Tasks
|
12
|
+
class BuildTask
|
13
|
+
def define; end
|
14
|
+
|
15
|
+
def build!; xcodebuild :build end
|
16
|
+
def archive!; xcodebuild :archive end
|
17
|
+
def clean!; xcodebuild :clean end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module FWToolkit
|
23
|
+
class Xcode < Thor
|
24
|
+
include Thor::Actions
|
25
|
+
include FWToolkit::ThorUtils
|
26
|
+
source_root_templates!
|
27
|
+
|
28
|
+
desc "new [PROJECT_NAME] [CLASS_PREFIX]", "Create a new Xcode project with FW's settings"
|
29
|
+
def new(project_name, class_prefix, root_dir=File.join(Dir.pwd, project_name))
|
30
|
+
say 'Creating Xcode project'
|
31
|
+
destination_root = root_dir
|
32
|
+
|
33
|
+
#raise Thor::Error, "Can't create the project. The directory #{destination_root} already exists" if Dir.exist?(destination_root)
|
34
|
+
|
35
|
+
Projectfile.load_with_config! :project_name => project_name, :class_prefix => class_prefix.upcase
|
36
|
+
|
37
|
+
template_config = { :target_platform => Config.target_platform,
|
38
|
+
:organization_name => Config.organization_name,
|
39
|
+
:project_creator => Config.developer_name }
|
40
|
+
template_config.merge! Projectfile.config
|
41
|
+
template_directory 'templates/default_project/xcode', destination_root, template_config
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "build [PROJECT_NAME]", "Compile a version of the Xcode project"
|
45
|
+
option :clean,
|
46
|
+
:type => :boolean,
|
47
|
+
:desc => 'Clean the project before building',
|
48
|
+
:default => true
|
49
|
+
option :archive,
|
50
|
+
:type => :boolean,
|
51
|
+
:desc => 'Archive the project after building',
|
52
|
+
:default => false
|
53
|
+
option :type,
|
54
|
+
:banner => 'type of build',
|
55
|
+
:desc => "The kind of build can be one of the following: dev, testing, release. Default: dev",
|
56
|
+
:default => 'dev'
|
57
|
+
option :sdk,
|
58
|
+
:banner => 'iphoneos/iphonesimulator',
|
59
|
+
:desc => "The platform to buy for: iphoneos or iphonesimulator. Default: iphoneos",
|
60
|
+
:default => 'iphoneos'
|
61
|
+
def build(project_dir)
|
62
|
+
build_types = ['dev', 'testing', 'release']
|
63
|
+
raise Thor::Error, 'Build type should be one of the following: dev, testing, release' unless build_types.include?(options[:type].downcase)
|
64
|
+
|
65
|
+
Projectfile.load! project_dir
|
66
|
+
output_dir = File.join artifacts_dir_for_project(Config.project_name), Projectfile.project_name
|
67
|
+
say_status :run, "Compiling the project and putting the output in: #{output_dir}", :blue
|
68
|
+
|
69
|
+
t = XcodeBuild::Tasks::BuildTask.new
|
70
|
+
t.invoke_from_within = 'project_dir'
|
71
|
+
t.sdk = options[:sdk]
|
72
|
+
t.workspace = Projectfile.xcode_workspace
|
73
|
+
t.scheme = Projectfile.xcode_scheme[options[:type].to_sym]
|
74
|
+
t.formatter = XcodeBuild::Formatters::ProgressFormatter.new
|
75
|
+
t.add_build_setting 'CONFIGURATION_BUILD_DIR', output_dir
|
76
|
+
|
77
|
+
if options[:clean]
|
78
|
+
FileUtils.rm_rf output_dir
|
79
|
+
t.clean!
|
80
|
+
end
|
81
|
+
options[:archive] ? t.archive! : t.build!
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
private
|
86
|
+
def artifacts_dir_for_project(project_name)
|
87
|
+
File.join Config.artifacts_tmp_dir, project_name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# :project_name -> OracleProject
|
93
|
+
# :binary_name -> OracleProject.app
|
94
|
+
# :class_prefix -> FWO
|
95
|
+
# :target_platform -> 6.0
|
96
|
+
# :provisioning
|
97
|
+
#
|
98
|
+
#binary_name -> app_name.app
|
99
|
+
#target_name -> app_name
|
100
|
+
#tests_target_name -> app_nameTests
|
101
|
+
#class_prefix -> XXX
|
102
|
+
#project_name -> app_name
|
103
|
+
#workspace_name -> app_name
|
104
|
+
#project_creator -> dev_name
|
105
|
+
#organization_name -> Future Workshops
|
data/lib/fwtoolkit/cli.rb
CHANGED
@@ -1,40 +1,31 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
|
1
|
+
require 'thor'
|
2
|
+
require 'fwtoolkit/config'
|
3
|
+
|
4
|
+
require 'fwtoolkit/cli/ext/thor'
|
5
|
+
require 'fwtoolkit/cli/fw_actions'
|
6
|
+
|
7
|
+
require 'fwtoolkit/cli/cocoapods'
|
8
|
+
require 'fwtoolkit/cli/xcode'
|
9
|
+
require 'fwtoolkit/cli/project'
|
10
|
+
require 'fwtoolkit/cli/bootstrap'
|
11
|
+
require 'fwtoolkit/cli/ci'
|
12
|
+
require 'fwtoolkit/cli/frank'
|
13
|
+
require 'fwtoolkit/cli/git'
|
14
|
+
#require 'fwtoolkit/cli/ota'
|
4
15
|
|
5
16
|
module FWToolkit
|
6
17
|
class CLI < Thor
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@no_prefix = options.no_prefix
|
19
|
-
|
20
|
-
model = CoreData::DataModel.new(File.join(core_data_model_path, 'contents'))
|
21
|
-
@models = model.entities
|
22
|
-
|
23
|
-
@models.each do |entity|
|
24
|
-
@model = entity
|
25
|
-
factory_template = File.join 'templates', 'models', 'model.rb.erb'
|
26
|
-
template(factory_template, File.join(output_dir, "#{class_name(@model).ruby_format}.rb"))
|
27
|
-
end
|
28
|
-
|
29
|
-
factory_template = File.join 'templates', 'models', 'factories.rb.erb'
|
30
|
-
template(factory_template, File.join(output_dir, 'factories.rb'))
|
31
|
-
end
|
32
|
-
|
33
|
-
no_tasks do
|
34
|
-
def class_name(entity)
|
35
|
-
@no_prefix ? entity.name : entity.name[3..-1]
|
36
|
-
end
|
37
|
-
end
|
18
|
+
|
19
|
+
register FWToolkit::Cocoapods, 'pods', 'pods SUBCOMMAND ...ARGS', 'Manage cocoapods'
|
20
|
+
register FWToolkit::Project, 'proj', 'proj SUBCOMMAND ...ARG', 'Create projects and manage settings'
|
21
|
+
register FWToolkit::Xcode, 'xcode', 'xcode SUBCOMMAND ...ARGS', 'Manage Xcode build process'
|
22
|
+
register FWToolkit::Bootstrap, 'bootstrap', 'bootstrap', 'Install and configure system tools'
|
23
|
+
register FWToolkit::Ci, 'ci', 'ci SUBCOMMAND ...ARGS', 'Manage the configuration of projects on the CI'
|
24
|
+
register FWToolkit::Frank, 'test', 'test SUBCOMMAND ...ARGS', 'Manage the testing framework'
|
25
|
+
|
26
|
+
register FWToolkit::Git, 'git', 'git SUBCOMMAND ...ARGS', 'Manage git flow'
|
27
|
+
#register FWToolkit::Ota, 'fwbuild', 'fwbuild SUBCOMMAND ...ARGS', 'Manage publishing build to the OTA server'
|
38
28
|
end
|
39
|
-
|
40
|
-
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'fwtoolkit/configfile'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module FWToolkit
|
5
|
+
module Config
|
6
|
+
include FWToolkit::ConfigFile
|
7
|
+
|
8
|
+
def self.config_file
|
9
|
+
File.join(ENV['HOME'], '.fwtoolkit', 'config')
|
10
|
+
end
|
11
|
+
|
12
|
+
def load!
|
13
|
+
unless File.exists? config_file
|
14
|
+
FileUtils.copy_file File.join(File.dirname(__FILE__), 'config', 'config.sample'), config_file
|
15
|
+
raise "Please configure fwtoolkit by editing the file at path: #{config_file}"
|
16
|
+
end
|
17
|
+
|
18
|
+
default_config = { :organization_name => 'Future Workshops',
|
19
|
+
:ruby_version => '1.9.3',
|
20
|
+
:target_platform => '6.0',
|
21
|
+
:ci_server_url => 'http://ci.office.futureworkshops.com',
|
22
|
+
:artifacts_tmp_dir => '/tmp/fwtoolkit/artifacts' }
|
23
|
+
|
24
|
+
load_config! config_file
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate_config
|
28
|
+
unless @config.has_key?(:developer_name)
|
29
|
+
raise NameError, "Please configure fwtoolkit by editing the file at path: #{config_file}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def conf_item_missing(name)
|
34
|
+
raise NoMethodError, "Please provide a valid '#{name}' by editing the conf file at path: #{config_file}"
|
35
|
+
end
|
36
|
+
|
37
|
+
extend self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
FWToolkit::Config.load!
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fwtoolkit/ext/hash_yaml'
|
2
|
+
|
3
|
+
# Mixin module that reads a yaml file into a hash and responds to config values
|
4
|
+
module FWToolkit
|
5
|
+
module ConfigFile
|
6
|
+
|
7
|
+
attr_accessor :default_config
|
8
|
+
|
9
|
+
def config
|
10
|
+
@config ||= Hash.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_config_hash!(config)
|
14
|
+
@config = config
|
15
|
+
merge_config @default_config if @default_config
|
16
|
+
validate_config if self.method_defined? :validate_config
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_config!(config_file)
|
20
|
+
load_config_hash! Hash.hash_from_yaml(config_file)
|
21
|
+
end
|
22
|
+
|
23
|
+
def merge_config(default_config)
|
24
|
+
default_config.each { |key, value| config[key] ||= value }
|
25
|
+
end
|
26
|
+
|
27
|
+
def configure
|
28
|
+
yield config
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(name, *args, &block)
|
32
|
+
puts name
|
33
|
+
config[name.to_sym] || conf_item_missing(name) if self.method_defined? :conf_item_missing
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module FWToolkit
|
2
|
+
module Executable
|
3
|
+
|
4
|
+
class ThorRunner
|
5
|
+
def run(command, config={})
|
6
|
+
Thor::Actions::run(command, config)
|
7
|
+
end
|
8
|
+
|
9
|
+
def report_error(command, command_output)
|
10
|
+
command_output.gsub!(/e\[\d+m/, '') #Stripping colors
|
11
|
+
say "An error has occured while running: \"#{command}\"", :red
|
12
|
+
say 'Command output:'
|
13
|
+
raise Thor::Error, "\n***\n#{command_output}***"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class CliRunner
|
18
|
+
def run(command, config={})
|
19
|
+
`#{command}`
|
20
|
+
end
|
21
|
+
|
22
|
+
def report_error(command, command_output)
|
23
|
+
command_output.gsub!(/e\[\d+m/, '')
|
24
|
+
puts "An error has occured while running: \"#{command}\"", :red
|
25
|
+
puts 'Command output:'
|
26
|
+
raise "\n***\n#{command_output}***"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.runner=(runner)
|
32
|
+
@@runner = runner
|
33
|
+
end
|
34
|
+
|
35
|
+
def run(command, options = {})
|
36
|
+
cmd_output = @@runner.run command, options
|
37
|
+
@@runner.report_error(command, cmd_output) if options[:raise_errors] && !$?.success?
|
38
|
+
end
|
39
|
+
|
40
|
+
def run!(command, options = {})
|
41
|
+
config.merge!({ :raise_errors => true })
|
42
|
+
run command config
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'fwtoolkit/executable/executable.rb'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
|
5
|
+
def self.hash_from_yaml(yaml_file)
|
6
|
+
YAML::load_file(yaml_file).symbolize!
|
7
|
+
end
|
8
|
+
|
9
|
+
def symbolize!
|
10
|
+
keys.each do |k|
|
11
|
+
self[k.to_sym] = delete(k)
|
12
|
+
self[k.to_sym].symbolize! if self[k.to_sym].is_a? Hash
|
13
|
+
end
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,225 @@
|
|
1
|
+
|
2
|
+
module GitClient
|
3
|
+
class GitError < StandardError
|
4
|
+
attr_reader :git_output
|
5
|
+
|
6
|
+
def initialize(git_output)
|
7
|
+
super
|
8
|
+
@git_output = git_output
|
9
|
+
end
|
10
|
+
|
11
|
+
def conflict?
|
12
|
+
git_output.any { |line| line.include? 'CONFLICT' }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Repository
|
17
|
+
def initialize(repo_path)
|
18
|
+
@repo_root = repo_path
|
19
|
+
@git_folder = File.join(repo_path, '.git')
|
20
|
+
@merge = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialized?
|
24
|
+
File.exists? @git_folder
|
25
|
+
end
|
26
|
+
|
27
|
+
def merging?
|
28
|
+
return @merge
|
29
|
+
end
|
30
|
+
|
31
|
+
def init
|
32
|
+
raise GitError.new("The folder #{@repo_root} already contains a git repository") if initialized?
|
33
|
+
git 'init'
|
34
|
+
end
|
35
|
+
|
36
|
+
def current_branch
|
37
|
+
current_branch = git('branch').split("\n").delete_if { |line| line[0] != "*" }
|
38
|
+
current_branch.first.gsub("* ", "")
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_files_to_index(files=nil)
|
42
|
+
files = files ? files : '.'
|
43
|
+
files = files.is_a?(Array) ? files : [files]
|
44
|
+
files.each do |file|
|
45
|
+
git "add \"#{file}\""
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def workdir_clean?
|
50
|
+
return status.empty?
|
51
|
+
end
|
52
|
+
# x index, y working_dir
|
53
|
+
# X Y Meaning
|
54
|
+
# -------------------------------------------------
|
55
|
+
# [MD] not updated
|
56
|
+
# M [ MD] updated in index
|
57
|
+
# A [ MD] added to index
|
58
|
+
# D [ M] deleted from index
|
59
|
+
# R [ MD] renamed in index
|
60
|
+
# C [ MD] copied in index
|
61
|
+
# [MARC] index and work tree matches
|
62
|
+
# [ MARC] M work tree changed since index
|
63
|
+
# [ MARC] D deleted in work tree
|
64
|
+
# -------------------------------------------------
|
65
|
+
# D D unmerged, both deleted
|
66
|
+
# A U unmerged, added by us
|
67
|
+
# U D unmerged, deleted by them
|
68
|
+
# U A unmerged, added by them
|
69
|
+
# D U unmerged, deleted by us
|
70
|
+
# A A unmerged, both added
|
71
|
+
# U U unmerged, both modified
|
72
|
+
# -------------------------------------------------
|
73
|
+
# ? ? untracked
|
74
|
+
# ! ! ignored
|
75
|
+
# -------------------------------------------------
|
76
|
+
|
77
|
+
def status
|
78
|
+
output = git 'status -s'
|
79
|
+
status_hash = Hash.new
|
80
|
+
return status_hash if output.length == 0 || merging?
|
81
|
+
|
82
|
+
output.split("\n").each do |entry|
|
83
|
+
raw_status = entry[0..1]
|
84
|
+
status = case raw_status ##needs to split leaving the freaking spaces on!
|
85
|
+
when / (M|D)/ then :idx_not_up_to_date
|
86
|
+
when /(A|M|R)M/ then :idx_not_up_to_date
|
87
|
+
when /A / then :idx_added
|
88
|
+
when /M / then :idx_modified
|
89
|
+
when /D / then :idx_deleted
|
90
|
+
when /R / then :idx_renamed
|
91
|
+
when /\?\?/ then :untracked
|
92
|
+
when /(DD|AA|(U|D|A)(U|D|A))/ then :merging
|
93
|
+
else :unknown
|
94
|
+
end
|
95
|
+
|
96
|
+
filename = entry.split(' ')[1]
|
97
|
+
status_hash[status] ||= []
|
98
|
+
status_hash[status] << filename
|
99
|
+
end
|
100
|
+
status_hash
|
101
|
+
end
|
102
|
+
|
103
|
+
def remotes
|
104
|
+
remotes = git 'remote -v'
|
105
|
+
remotes_hash = Hash.new
|
106
|
+
remotes.split("\n").each do |line|
|
107
|
+
split = line.split(' ')[0..1]
|
108
|
+
remotes_hash[symbolicate(split[0])] = split[1]
|
109
|
+
end if remotes
|
110
|
+
remotes_hash
|
111
|
+
end
|
112
|
+
|
113
|
+
def submodules
|
114
|
+
submodules_hash = Hash.new
|
115
|
+
return submodules_hash unless File.exists? File.join(@repo_root, '.gitmodules')
|
116
|
+
|
117
|
+
submodules = git "config -f .gitmodules --get-regexp '^submodule\..*\.path$'"
|
118
|
+
submodules.split("\n").each do |line|
|
119
|
+
split = line.split(' ')[0..1]
|
120
|
+
submodule_name = split[0][/^submodule.(.*).path$/, 1]
|
121
|
+
submodule_path = split[1]
|
122
|
+
submodule_remote = (git "config -f .gitmodules --get-all 'submodule.#{submodule_name}.url'").delete "\n"
|
123
|
+
|
124
|
+
submodules_hash[submodule_path] = submodule_remote
|
125
|
+
end
|
126
|
+
submodules_hash
|
127
|
+
end
|
128
|
+
|
129
|
+
def submodules_update(conf)
|
130
|
+
return if submodules.empty?
|
131
|
+
git "submodule init" if(conf[:init])
|
132
|
+
git "submodule update --recursive"
|
133
|
+
end
|
134
|
+
|
135
|
+
def branch_exist?(branch_name)
|
136
|
+
git('branch').split("\n").any? { |line| line.include? branch_name }
|
137
|
+
end
|
138
|
+
|
139
|
+
def ensure_branch_exists(branch_name)
|
140
|
+
return if branch_exist? branch_name
|
141
|
+
raise GitError, "Branch #{branch_name} doesn't exists"
|
142
|
+
end
|
143
|
+
|
144
|
+
def ensure_workdir_clean
|
145
|
+
return if workdir_clean?
|
146
|
+
raise GitError, 'The working directory is not clean'
|
147
|
+
end
|
148
|
+
|
149
|
+
# returns the commit hash
|
150
|
+
def commit(message)
|
151
|
+
output = git "commit -m\"#{message}\""
|
152
|
+
output[/\[\w* (\w*)\] .*/,1]
|
153
|
+
end
|
154
|
+
|
155
|
+
def switch_branch(branch_name, force_create=true)
|
156
|
+
ensure_branch_exists branch_name unless force_create
|
157
|
+
|
158
|
+
git "branch #{branch_name}" if force_create && !branch_exist?(branch_name)
|
159
|
+
git "checkout \"#{branch_name}\"" unless current_branch == branch_name
|
160
|
+
end
|
161
|
+
|
162
|
+
def merge(from_branch, into_branch=nil, msg=nil)
|
163
|
+
ensure_branch_exists from_branch
|
164
|
+
ensure_branch_exists into_branch if into_branch
|
165
|
+
|
166
|
+
ensure_workdir_clean
|
167
|
+
git "checkout \"#{into_branch}\""
|
168
|
+
|
169
|
+
begin
|
170
|
+
merge = true
|
171
|
+
msg.nil? ? git("merge --no-ff #{from_branch}"): git("merge --no-ff #{from_branch} -m \"#{msg}\"")
|
172
|
+
rescue GitError => e
|
173
|
+
git 'merge --abort' if e.conflict?
|
174
|
+
merge = false
|
175
|
+
raise e
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def save_stash
|
180
|
+
git 'stash save'
|
181
|
+
end
|
182
|
+
|
183
|
+
def pop_stash
|
184
|
+
git 'stash pop'
|
185
|
+
end
|
186
|
+
|
187
|
+
def rebase(from_branch, into_branch=nil)
|
188
|
+
ensure_branch_exists from_branch
|
189
|
+
ensure_branch_exists into_branch if into_branch
|
190
|
+
ensure_workdir_clean
|
191
|
+
|
192
|
+
git "checkout \"#{into_branch}\""
|
193
|
+
begin
|
194
|
+
merge = true
|
195
|
+
git "rebase \"#{from_branch}\""
|
196
|
+
rescue GitError => e
|
197
|
+
git 'rebase --abort' if e.conflict?
|
198
|
+
merge = false
|
199
|
+
raise e
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
private
|
204
|
+
|
205
|
+
# good way of making this more robust:
|
206
|
+
# https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/executable.rb
|
207
|
+
# and:
|
208
|
+
# https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/downloader/git.rb
|
209
|
+
def git(git_cmd)
|
210
|
+
output = nil
|
211
|
+
FileUtils.cd(@repo_root) { output = safe_exec("git #{git_cmd}") }
|
212
|
+
output
|
213
|
+
end
|
214
|
+
|
215
|
+
def safe_exec(cmd)
|
216
|
+
cmd_output = `#{cmd} 2>&1 3>&1`
|
217
|
+
raise GitError.new(cmd_output) unless $?.success?
|
218
|
+
cmd_output
|
219
|
+
end
|
220
|
+
|
221
|
+
def symbolicate(string)
|
222
|
+
string.gsub(/\s+/, "_").downcase.to_sym
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'fwtoolkit/git_client/git_client'
|