Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
cocoapods
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gengmeiios
cocoapods
Commits
9b013470
Commit
9b013470
authored
Oct 04, 2017
by
Dimitris Koutsogiorgas
Committed by
GitHub
Oct 04, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7092 from dnkoutso/script_phase_podspec
Add support to integrate script phases from podspecs
parents
10daf0bf
c23607a6
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
230 additions
and
123 deletions
+230
-123
CHANGELOG.md
CHANGELOG.md
+4
-0
Gemfile.lock
Gemfile.lock
+1
-1
pod_target_integrator.rb
...nstaller/pods_project_integrator/pod_target_integrator.rb
+0
-85
target_integrator.rb
...ds/installer/user_project_integrator/target_integrator.rb
+38
-32
pods_project_generator.rb
lib/cocoapods/installer/xcode/pods_project_generator.rb
+5
-5
pod_target_integrator.rb
...ler/xcode/pods_project_generator/pod_target_integrator.rb
+101
-0
pod_target_integrator_spec.rb
...code/pods_project_generator/pod_target_integrator_spec.rb
+81
-0
No files found.
CHANGELOG.md
View file @
9b013470
...
@@ -8,6 +8,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
...
@@ -8,6 +8,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
##### Enhancements
##### Enhancements
*
Add support to integrate script phases from podspecs
[
Dimitris Koutsogiorgas
](
https://github.com/dnkoutso
)
[
#7092
](
https://github.com/CocoaPods/CocoaPods/pull/7092
)
*
Add support for preventing pch file generation with the skip_pch podspec attribute
*
Add support for preventing pch file generation with the skip_pch podspec attribute
[
Paul Beusterien
](
https://github.com/paulb777
)
[
Paul Beusterien
](
https://github.com/paulb777
)
[
#7044
](
https://github.com/CocoaPods/CocoaPods/pull/7044
)
[
#7044
](
https://github.com/CocoaPods/CocoaPods/pull/7044
)
...
...
Gemfile.lock
View file @
9b013470
...
@@ -7,7 +7,7 @@ GIT
...
@@ -7,7 +7,7 @@ GIT
GIT
GIT
remote: https://github.com/CocoaPods/Core.git
remote: https://github.com/CocoaPods/Core.git
revision:
283ac03a69984faab02c03ad65871966f7581481
revision:
3f98bce41fd8eb6d385441eef4e5611665d13e64
branch: master
branch: master
specs:
specs:
cocoapods-core (1.4.0.beta.1)
cocoapods-core (1.4.0.beta.1)
...
...
lib/cocoapods/installer/pods_project_integrator/pod_target_integrator.rb
deleted
100644 → 0
View file @
10daf0bf
module
Pod
class
Installer
# This class is responsible for integrating a pod target. This includes integrating
# the test targets included by each pod target.
#
class
PodTargetIntegrator
# @return [PodTarget] the target that should be integrated.
#
attr_reader
:target
# Init a new PodTargetIntegrator.
#
# @param [PodTarget] target @see #target
#
def
initialize
(
target
)
@target
=
target
end
# Integrates the pod target.
#
# @return [void]
#
def
integrate!
UI
.
section
(
integration_message
)
do
target
.
test_native_targets
.
each
do
|
native_target
|
add_embed_frameworks_script_phase
(
native_target
)
add_copy_resources_script_phase
(
native_target
)
end
end
end
# @return [String] a string representation suitable for debugging.
#
def
inspect
"#<
#{
self
.
class
}
for target `
#{
target
.
label
}
'>"
end
private
# @!group Integration steps
#---------------------------------------------------------------------#
# Find or create a 'Copy Pods Resources' build phase
#
# @return [void]
#
def
add_copy_resources_script_phase
(
native_target
)
test_type
=
target
.
test_type_for_product_type
(
native_target
.
symbol_type
)
script_path
=
"${PODS_ROOT}/
#{
target
.
copy_resources_script_path_for_test_type
(
test_type
).
relative_path_from
(
target
.
sandbox
.
root
)
}
"
resource_paths
=
target
.
all_test_dependent_targets
.
flat_map
(
&
:resource_paths
)
input_paths
=
[]
output_paths
=
[]
unless
resource_paths
.
empty?
input_paths
=
[
script_path
,
*
resource_paths
.
flatten
.
uniq
]
output_paths
=
[
'${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}'
]
end
Pod
::
Installer
::
UserProjectIntegrator
::
TargetIntegrator
.
add_copy_resources_script_phase_to_target
(
native_target
,
script_path
,
input_paths
,
output_paths
)
end
# Find or create a 'Embed Pods Frameworks' Copy Files Build Phase
#
# @return [void]
#
def
add_embed_frameworks_script_phase
(
native_target
)
test_type
=
target
.
test_type_for_product_type
(
native_target
.
symbol_type
)
script_path
=
"${PODS_ROOT}/
#{
target
.
embed_frameworks_script_path_for_test_type
(
test_type
).
relative_path_from
(
target
.
sandbox
.
root
)
}
"
framework_paths
=
target
.
all_test_dependent_targets
.
flat_map
(
&
:framework_paths
)
input_paths
=
[]
output_paths
=
[]
unless
framework_paths
.
empty?
input_paths
=
[
script_path
,
*
framework_paths
.
map
{
|
fw
|
[
fw
[
:input_path
],
fw
[
:dsym_input_path
]]
}.
flatten
.
compact
]
output_paths
=
framework_paths
.
map
{
|
fw
|
[
fw
[
:output_path
],
fw
[
:dsym_output_path
]]
}.
flatten
.
compact
end
Pod
::
Installer
::
UserProjectIntegrator
::
TargetIntegrator
.
add_embed_frameworks_script_phase_to_target
(
native_target
,
script_path
,
input_paths
,
output_paths
)
end
# @return [String] the message that should be displayed for the target
# integration.
#
def
integration_message
"Integrating target `
#{
target
.
name
}
`"
end
end
end
end
lib/cocoapods/installer/user_project_integrator/target_integrator.rb
View file @
9b013470
...
@@ -147,6 +147,41 @@ module Pod
...
@@ -147,6 +147,41 @@ module Pod
end
end
end
end
end
end
# Updates all target script phases for the current target, including creating or updating, deleting
# and re-ordering.
#
# @return [void]
#
def
create_or_update_user_script_phases
(
script_phases
,
native_target
)
script_phase_names
=
script_phases
.
map
{
|
k
|
k
[
:name
]
}
# Delete script phases no longer present in the target definition.
native_target_script_phases
=
native_target
.
shell_script_build_phases
.
select
{
|
bp
|
!
bp
.
name
.
nil?
&&
bp
.
name
.
start_with?
(
USER_BUILD_PHASE_PREFIX
)
}
native_target_script_phases
.
each
do
|
script_phase
|
script_phase_name_without_prefix
=
script_phase
.
name
.
sub
(
USER_BUILD_PHASE_PREFIX
,
''
)
unless
script_phase_names
.
include?
(
script_phase_name_without_prefix
)
native_target
.
build_phases
.
delete
(
script_phase
)
end
end
# Create or update the ones that are expected to be.
script_phases
.
each
do
|
td_script_phase
|
phase
=
TargetIntegrator
.
create_or_update_build_phase
(
native_target
,
USER_BUILD_PHASE_PREFIX
+
td_script_phase
[
:name
])
phase
.
shell_script
=
td_script_phase
[
:script
]
phase
.
shell_path
=
td_script_phase
[
:shell_path
]
if
td_script_phase
.
key?
(
:shell_path
)
phase
.
input_paths
=
td_script_phase
[
:input_files
]
if
td_script_phase
.
key?
(
:input_files
)
phase
.
output_paths
=
td_script_phase
[
:output_files
]
if
td_script_phase
.
key?
(
:output_files
)
phase
.
show_env_vars_in_log
=
td_script_phase
[
:show_env_vars_in_log
]
?
'1'
:
'0'
if
td_script_phase
.
key?
(
:show_env_vars_in_log
)
end
# Move script phases to their correct index if the order has changed.
offset
=
native_target
.
build_phases
.
count
-
script_phases
.
count
script_phases
.
each_with_index
do
|
td_script_phase
,
index
|
current_index
=
native_target
.
build_phases
.
index
do
|
bp
|
bp
.
is_a?
(
Xcodeproj
::
Project
::
Object
::
PBXShellScriptBuildPhase
)
&&
bp
.
name
.
sub
(
USER_BUILD_PHASE_PREFIX
,
''
)
==
td_script_phase
[
:name
]
end
expected_index
=
offset
+
index
native_target
.
build_phases
.
insert
(
expected_index
,
native_target
.
build_phases
.
delete_at
(
current_index
))
if
current_index
!=
expected_index
end
end
end
end
# Integrates the user project targets. Only the targets that do **not**
# Integrates the user project targets. Only the targets that do **not**
...
@@ -164,7 +199,7 @@ module Pod
...
@@ -164,7 +199,7 @@ module Pod
remove_embed_frameworks_script_phase_from_embedded_targets
remove_embed_frameworks_script_phase_from_embedded_targets
add_copy_resources_script_phase
add_copy_resources_script_phase
add_check_manifest_lock_script_phase
add_check_manifest_lock_script_phase
update_target
_script_phases
add_user
_script_phases
end
end
end
end
...
@@ -265,38 +300,9 @@ module Pod
...
@@ -265,38 +300,9 @@ module Pod
#
#
# @return [void]
# @return [void]
#
#
def
update_target_script_phases
def
add_user_script_phases
target_definition_script_phases
=
target
.
target_definition
.
script_phases
target_definition_script_phase_names
=
target_definition_script_phases
.
map
{
|
k
|
k
[
:name
]
}
native_targets
.
each
do
|
native_target
|
native_targets
.
each
do
|
native_target
|
# Delete script phases no longer present in the target definition.
TargetIntegrator
.
create_or_update_user_script_phases
(
target
.
target_definition
.
script_phases
,
native_target
)
native_target_script_phases
=
native_target
.
shell_script_build_phases
.
select
{
|
bp
|
!
bp
.
name
.
nil?
&&
bp
.
name
.
start_with?
(
USER_BUILD_PHASE_PREFIX
)
}
native_target_script_phases
.
each
do
|
script_phase
|
script_phase_name_without_prefix
=
script_phase
.
name
.
sub
(
USER_BUILD_PHASE_PREFIX
,
''
)
unless
target_definition_script_phase_names
.
include?
(
script_phase_name_without_prefix
)
native_target
.
build_phases
.
delete
(
script_phase
)
end
end
# Create or update the ones that are expected to be.
target_definition_script_phases
.
each
do
|
td_script_phase
|
phase
=
TargetIntegrator
.
create_or_update_build_phase
(
native_target
,
USER_BUILD_PHASE_PREFIX
+
td_script_phase
[
:name
])
phase
.
shell_script
=
td_script_phase
[
:script
]
phase
.
shell_path
=
td_script_phase
[
:shell_path
]
if
td_script_phase
.
key?
(
:shell_path
)
phase
.
input_paths
=
td_script_phase
[
:input_files
]
if
td_script_phase
.
key?
(
:input_files
)
phase
.
output_paths
=
td_script_phase
[
:output_files
]
if
td_script_phase
.
key?
(
:output_files
)
phase
.
show_env_vars_in_log
=
td_script_phase
[
:show_env_vars_in_log
]
?
'1'
:
'0'
if
td_script_phase
.
key?
(
:show_env_vars_in_log
)
end
# Move script phases to their correct index if the order has changed.
offset
=
native_target
.
build_phases
.
count
-
target_definition_script_phases
.
count
target_definition_script_phases
.
each_with_index
do
|
td_script_phase
,
index
|
current_index
=
native_target
.
build_phases
.
index
do
|
bp
|
bp
.
is_a?
(
Xcodeproj
::
Project
::
Object
::
PBXShellScriptBuildPhase
)
&&
bp
.
name
.
sub
(
USER_BUILD_PHASE_PREFIX
,
''
)
==
td_script_phase
[
:name
]
end
expected_index
=
offset
+
index
native_target
.
build_phases
.
insert
(
expected_index
,
native_target
.
build_phases
.
delete_at
(
current_index
))
if
current_index
!=
expected_index
end
end
end
end
end
...
...
lib/cocoapods/installer/xcode/pods_project_generator.rb
View file @
9b013470
...
@@ -4,7 +4,7 @@ module Pod
...
@@ -4,7 +4,7 @@ module Pod
# The {PodsProjectGenerator} handles generation of the 'Pods/Pods.xcodeproj'
# The {PodsProjectGenerator} handles generation of the 'Pods/Pods.xcodeproj'
#
#
class
PodsProjectGenerator
class
PodsProjectGenerator
require
'cocoapods/installer/
pods_project_integ
rator/pod_target_integrator'
require
'cocoapods/installer/
xcode/pods_project_gene
rator/pod_target_integrator'
require
'cocoapods/installer/xcode/pods_project_generator/target_installer'
require
'cocoapods/installer/xcode/pods_project_generator/target_installer'
require
'cocoapods/installer/xcode/pods_project_generator/pod_target_installer'
require
'cocoapods/installer/xcode/pods_project_generator/pod_target_installer'
require
'cocoapods/installer/xcode/pods_project_generator/file_references_installer'
require
'cocoapods/installer/xcode/pods_project_generator/file_references_installer'
...
@@ -63,7 +63,7 @@ module Pod
...
@@ -63,7 +63,7 @@ module Pod
prepare
prepare
install_file_references
install_file_references
install_libraries
install_libraries
integrate_t
est_t
argets
integrate_targets
set_target_dependencies
set_target_dependencies
end
end
...
@@ -179,12 +179,12 @@ module Pod
...
@@ -179,12 +179,12 @@ module Pod
end
end
end
end
def
integrate_t
est_t
argets
def
integrate_targets
pod_targets_with_test_targets
=
pod_targets
.
reject
{
|
pt
|
pt
.
test_native_targets
.
empty?
}
pod_targets_with_test_targets
=
pod_targets
.
reject
{
|
pt
|
pt
.
test_native_targets
.
empty?
}
unless
pod_targets_with_test_targets
.
empty?
unless
pod_targets_with_test_targets
.
empty?
UI
.
message
'- Integrating t
est t
argets'
do
UI
.
message
'- Integrating targets'
do
pod_targets_with_test_targets
.
each
do
|
pod_target
|
pod_targets_with_test_targets
.
each
do
|
pod_target
|
Pod
::
Installer
::
Pod
TargetIntegrator
.
new
(
pod_target
).
integrate!
PodTargetIntegrator
.
new
(
pod_target
).
integrate!
end
end
end
end
end
end
...
...
lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb
0 → 100644
View file @
9b013470
module
Pod
class
Installer
class
Xcode
class
PodsProjectGenerator
# This class is responsible for integrating a pod target. This includes integrating
# the test targets included by each pod target.
#
class
PodTargetIntegrator
# @return [PodTarget] the target that should be integrated.
#
attr_reader
:target
# Init a new PodTargetIntegrator.
#
# @param [PodTarget] target @see #target
#
def
initialize
(
target
)
@target
=
target
end
# Integrates the pod target.
#
# @return [void]
#
def
integrate!
UI
.
section
(
integration_message
)
do
target
.
test_specs_by_native_target
.
each
do
|
native_target
,
test_specs
|
add_embed_frameworks_script_phase
(
native_target
)
add_copy_resources_script_phase
(
native_target
)
UserProjectIntegrator
::
TargetIntegrator
.
create_or_update_user_script_phases
(
script_phases_for_specs
(
test_specs
),
native_target
)
end
specs
=
target
.
specs
.
reject
(
&
:test_specification?
)
UserProjectIntegrator
::
TargetIntegrator
.
create_or_update_user_script_phases
(
script_phases_for_specs
(
specs
),
target
.
native_target
)
end
end
# @return [String] a string representation suitable for debugging.
#
def
inspect
"#<
#{
self
.
class
}
for target `
#{
target
.
label
}
'>"
end
private
# @!group Integration steps
#---------------------------------------------------------------------#
# Find or create a 'Copy Pods Resources' build phase
#
# @return [void]
#
def
add_copy_resources_script_phase
(
native_target
)
test_type
=
target
.
test_type_for_product_type
(
native_target
.
symbol_type
)
script_path
=
"${PODS_ROOT}/
#{
target
.
copy_resources_script_path_for_test_type
(
test_type
).
relative_path_from
(
target
.
sandbox
.
root
)
}
"
resource_paths
=
target
.
all_test_dependent_targets
.
flat_map
(
&
:resource_paths
)
input_paths
=
[]
output_paths
=
[]
unless
resource_paths
.
empty?
input_paths
=
[
script_path
,
*
resource_paths
.
flatten
.
uniq
]
output_paths
=
[
'${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}'
]
end
UserProjectIntegrator
::
TargetIntegrator
.
add_copy_resources_script_phase_to_target
(
native_target
,
script_path
,
input_paths
,
output_paths
)
end
# Find or create a 'Embed Pods Frameworks' Copy Files Build Phase
#
# @return [void]
#
def
add_embed_frameworks_script_phase
(
native_target
)
test_type
=
target
.
test_type_for_product_type
(
native_target
.
symbol_type
)
script_path
=
"${PODS_ROOT}/
#{
target
.
embed_frameworks_script_path_for_test_type
(
test_type
).
relative_path_from
(
target
.
sandbox
.
root
)
}
"
framework_paths
=
target
.
all_test_dependent_targets
.
flat_map
(
&
:framework_paths
)
input_paths
=
[]
output_paths
=
[]
unless
framework_paths
.
empty?
input_paths
=
[
script_path
,
*
framework_paths
.
map
{
|
fw
|
[
fw
[
:input_path
],
fw
[
:dsym_input_path
]]
}.
flatten
.
compact
]
output_paths
=
framework_paths
.
map
{
|
fw
|
[
fw
[
:output_path
],
fw
[
:dsym_output_path
]]
}.
flatten
.
compact
end
UserProjectIntegrator
::
TargetIntegrator
.
add_embed_frameworks_script_phase_to_target
(
native_target
,
script_path
,
input_paths
,
output_paths
)
end
# @return [String] the message that should be displayed for the target
# integration.
#
def
integration_message
"Integrating target `
#{
target
.
name
}
`"
end
# @param [Array<Specification] specs
# the specs to return script phrases from.
#
# @return [Array<Hash<Symbol=>String>] an array of all combined script phases from the specs.
#
def
script_phases_for_specs
(
specs
)
specs
.
map
{
|
spec
|
spec
.
consumer
(
target
.
platform
)
}.
map
(
&
:script_phases
).
flatten
end
end
end
end
end
end
spec/unit/installer/xcode/pods_project_generator/pod_target_integrator_spec.rb
0 → 100644
View file @
9b013470
require
File
.
expand_path
(
'../../../../../spec_helper'
,
__FILE__
)
module
Pod
class
Installer
class
Xcode
class
PodsProjectGenerator
class
PodTargetIntegrator
describe
'In general'
do
before
do
@project
=
Pod
::
Project
.
new
(
config
.
sandbox
.
project_path
)
@project
.
save
@target_definition
=
fixture_target_definition
@coconut_spec
=
fixture_spec
(
'coconut-lib/CoconutLib.podspec'
)
@coconut_pod_target
=
PodTarget
.
new
([
@coconut_spec
,
*
@coconut_spec
.
recursive_subspecs
],
[
@target_definition
],
config
.
sandbox
)
@native_target
=
stub
(
'NativeTarget'
,
:shell_script_build_phases
=>
[],
:build_phases
=>
[],
:project
=>
@project
)
@test_native_target
=
stub
(
'TestNativeTarget'
,
:symbol_type
=>
:unit_test_bundle
,
:build_phases
=>
[],
:shell_script_build_phases
=>
[],
:project
=>
@project
)
@coconut_pod_target
.
stubs
(
:native_target
).
returns
(
@native_target
)
@coconut_pod_target
.
stubs
(
:test_native_targets
).
returns
([
@test_native_target
])
end
describe
'#integrate!'
do
it
'integrates test native targets with frameworks and resources script phases'
do
PodTargetIntegrator
.
new
(
@coconut_pod_target
).
integrate!
@test_native_target
.
build_phases
.
count
.
should
==
2
@test_native_target
.
build_phases
.
map
(
&
:display_name
).
should
==
[
'[CP] Embed Pods Frameworks'
,
'[CP] Copy Pods Resources'
,
]
@test_native_target
.
build_phases
[
0
].
shell_script
.
should
==
"
\"
${PODS_ROOT}/Target Support Files/CoconutLib/CoconutLib-Unit-Tests-frameworks.sh
\"\n
"
@test_native_target
.
build_phases
[
1
].
shell_script
.
should
==
"
\"
${PODS_ROOT}/Target Support Files/CoconutLib/CoconutLib-Unit-Tests-resources.sh
\"\n
"
end
it
'integrates test native targets with frameworks and resources script phase input and output paths'
do
framework_paths
=
{
:name
=>
'Vendored.framework'
,
:input_path
=>
'${PODS_ROOT}/Vendored/Vendored.framework'
,
:output_path
=>
'${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Vendored.framework'
}
resource_paths
=
[
'${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle'
]
@coconut_pod_target
.
stubs
(
:framework_paths
).
returns
(
framework_paths
)
@coconut_pod_target
.
stubs
(
:resource_paths
).
returns
(
resource_paths
)
PodTargetIntegrator
.
new
(
@coconut_pod_target
).
integrate!
@test_native_target
.
build_phases
.
count
.
should
==
2
@test_native_target
.
build_phases
.
map
(
&
:display_name
).
should
==
[
'[CP] Embed Pods Frameworks'
,
'[CP] Copy Pods Resources'
,
]
@test_native_target
.
build_phases
[
0
].
input_paths
.
should
==
[
'${PODS_ROOT}/Target Support Files/CoconutLib/CoconutLib-Unit-Tests-frameworks.sh'
,
'${PODS_ROOT}/Vendored/Vendored.framework'
,
]
@test_native_target
.
build_phases
[
0
].
output_paths
.
should
==
[
'${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Vendored.framework'
,
]
@test_native_target
.
build_phases
[
1
].
input_paths
.
should
==
[
'${PODS_ROOT}/Target Support Files/CoconutLib/CoconutLib-Unit-Tests-resources.sh'
,
'${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle'
,
]
@test_native_target
.
build_phases
[
1
].
output_paths
.
should
==
[
'${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}'
,
]
end
it
'integrates test native target with shell script phases'
do
@coconut_spec
.
test_specs
.
first
.
script_phase
=
{
:name
=>
'Hello World'
,
:script
=>
'echo "Hello World"'
}
PodTargetIntegrator
.
new
(
@coconut_pod_target
).
integrate!
@test_native_target
.
build_phases
.
count
.
should
==
3
@test_native_target
.
build_phases
[
2
].
display_name
.
should
==
'[CP-User] Hello World'
@test_native_target
.
build_phases
[
2
].
shell_script
.
should
==
'echo "Hello World"'
end
it
'integrates native target with shell script phases'
do
@coconut_spec
.
script_phase
=
{
:name
=>
'Hello World'
,
:script
=>
'echo "Hello World"'
}
PodTargetIntegrator
.
new
(
@coconut_pod_target
).
integrate!
@native_target
.
build_phases
.
count
.
should
==
1
@native_target
.
build_phases
[
0
].
display_name
.
should
==
'[CP-User] Hello World'
@native_target
.
build_phases
[
0
].
shell_script
.
should
==
'echo "Hello World"'
end
end
end
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment