fwtoolkit 0.9.3 → 1.0.1
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.
- 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'
|