diff --git a/README.md b/README.md
index e3f9a7c..6835bab 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ Let's make an empty file named **Seedfile** in the directory where your Xcode pr
github "Alamofire/Alamofire", "1.2.1", :files => "Source/*.{swift,h}"
github "devxoul/JLToast", "1.2.5", :files => "JLToast/*.{swift,h}"
github "devxoul/SwipeBack", "1.0.4"
-github "Masonry/SnapKit", "0.10.0", :files => "Source/*.{swift,h}"
+github "SnapKit/SnapKit", :commit => "62e7645", :files => "Source/*.{swift,h}"
target :MyAppTest do
github "Quick/Quick", "v0.3.1", :files => "Quick/**.{swift,h}"
@@ -58,14 +58,14 @@ Each line in a Seedfile consists of three parts: source, tag, and files. Let's l
```ruby
github "devxoul/JLToast", "1.2.5", :files => "JLToast/*.{swift,h}"
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- (Source) (Tag) (Files)
+ (Source) (Version) (Files)
```
-| Parts | Example | Required | Default |
-|--------|-----------------------------------|:--------:|:---------------------:|
-| Source | `github "devxoul/SwipeBack"` | Required | - |
-| Tag | `1.0.4` | Required | - |
-| Files | `:files => "JLToast/*.{swift,h}"` | Optional | `*/**.{h,m,mm,swift}` |
+| Parts | Example | Required | Default |
+|---------|-----------------------------------|:--------:|:---------------------:|
+| Source | `github "devxoul/SwipeBack"` | Required | - |
+| Version | Tag: `"1.0.4"`
Branch: `"swift-2.0"`
Commit: `:commit => "SHA1"` | Required | - |
+| Files | `:files => "JLToast/*.{swift,h}"` | Optional | `*/**.{h,m,mm,swift}` |
> **Tip:** You can pass an array to `:files` for multiple file patterns:
>
diff --git a/lib/cocoaseeds/core.rb b/lib/cocoaseeds/core.rb
index c5cceaa..f99e9c3 100644
--- a/lib/cocoaseeds/core.rb
+++ b/lib/cocoaseeds/core.rb
@@ -161,6 +161,10 @@ def analyze_dependencies
seed = Seeds::Seed.new
seed.name = lock.split(' (')[0]
seed.version = lock.split('(')[1].split(')')[0]
+ if seed.version.start_with? '$'
+ seed.commit = seed.version[1..-1]
+ seed.version = nil
+ end
self.locks[seed.name] = seed
end
end
@@ -224,8 +228,17 @@ def github(repo, tag, options={})
seed = Seeds::Seed::GitHub.new
seed.url = "https://github.com/#{repo}"
seed.name = repo.split('/')[1]
- seed.version = tag
- seed.files = options[:files] || '**/*.{h,m,mm,swift}'
+ if tag.is_a?(String)
+ if options[:commit]
+ raise Seeds::Exception.new\
+ "#{repo}: Version and commit are both specified."
+ end
+ seed.version = tag
+ seed.files = options[:files] || '**/*.{h,m,mm,swift}'
+ elsif tag.is_a?(Hash)
+ seed.commit = tag[:commit][0..6]
+ seed.files = tag[:files] || '**/*.{h,m,mm,swift}'
+ end
if seed.files.kind_of?(String)
seed.files = [seed.files]
end
@@ -256,8 +269,17 @@ def bitbucket(repo, tag, options={})
seed = Seeds::Seed::BitBucket.new
seed.url = "https://bitbucket.org/#{repo}"
seed.name = repo.split('/')[1]
- seed.version = tag
- seed.files = options[:files] || '**/*.{h,m,mm,swift}'
+ if tag.is_a?(String)
+ if options[:commit]
+ raise Seeds::Exception.new\
+ "#{repo}: Version and commit are both specified."
+ end
+ seed.version = tag
+ seed.files = options[:files] || '**/*.{h,m,mm,swift}'
+ elsif tag.is_a?(Hash)
+ seed.commit = tag[:commit][0..6]
+ seed.files = tag[:files] || '**/*.{h,m,mm,swift}'
+ end
if seed.files.kind_of?(String)
seed.files = [seed.files]
end
@@ -289,53 +311,97 @@ def remove_seeds
#
def install_seeds
self.seeds.sort.each do |name, seed|
- dirname = File.join(self.root_path, "Seeds", name)
+ dirname = File.join(self.root_path, "Seeds", seed.name)
+ self.install_seed(seed, dirname)
+
+ next if not seed.files
+
+ # add seed files to `source_files`
+ self.source_files[name] = []
+ seed.files.each do |file|
+ paths = Dir.glob(File.join(dirname, file))
+ paths.each do |path|
+ path = self.path_with_prefix(seed.name, path)
+ self.source_files[name].push(path)
+ end
+ end
+ end
+ end
- if lock = self.locks[name]
- old_version = lock.version
+
+ # Installs new seed or updates existing seed in {#dirname}.
+ #
+ # @!visibility private
+ #
+ def install_seed(seed, dirname)
+ # clone and return if not exists
+ if not File.exist?(dirname)
+ say "Installing #{seed.name} (#{seed.version or seed.commit})".green
+
+ command = "git clone #{seed.url}"
+ command += " -b #{seed.version}" if seed.version
+ command += " #{dirname} 2>&1"
+ output = `#{command}`
+
+ not_found = output.include?("not found")
+ if not_found and output.include?("repository")
+ say "[!] #{seed.name}: Couldn't find the repository.".red
+ elsif not_found and output.include?("upstream")
+ say "[!] #{seed.name}: Couldn't find the tag `#{seed.version}`.".red
end
- if File.exist?(dirname)
- tag = `cd #{dirname} && git describe --tags --abbrev=0 2>&1`
- tag.strip!
- if tag == seed.version and (not old_version or tag == old_version)
- say "Using #{name} (#{seed.version})"
- `cd #{dirname} 2>&1 &&\
- git reset HEAD --hard 2>&1 &&\
- git checkout . 2>&1 &&\
- git clean -fd 2>&1`
- else
- say "Installing #{name} #{seed.version} (was #{old_version})".green
- `cd #{dirname} 2>&1 &&\
- git reset HEAD --hard 2>&1 &&\
- git checkout . 2>&1 &&\
- git clean -fd 2>&1 &&\
- git fetch origin #{seed.version} --tags 2>&1 &&\
- git checkout #{seed.version} 2>&1`
- end
- else
- say "Installing #{name} (#{seed.version})".green
- output = `git clone #{seed.url} -b #{seed.version} #{dirname} 2>&1`
- if output.include?("not found")
- if output.include?("repository")
- say "[!] #{name}: Couldn't find the repository.".red
- elsif output.include?("upstream")
- say "[!] #{name}: Couldn't find the tag `#{seed.version}`.".red
- end
+ if seed.commit and not seed.version # checkout to commit
+ output = `cd #{dirname} 2>&1 && git checkout #{seed.commit} 2>&1`
+ if output.include?("did not match any")
+ say "[!] #{seed.name}: Couldn't find the commit "\
+ "`#{seed.commit}`.".red
end
end
- if seed.files
- self.source_files[name] = []
- seed.files.each do |file|
- paths = Dir.glob(File.join(dirname, file))
- paths.each do |path|
- path = self.path_with_prefix(seed.name, path)
- self.source_files[name].push(path)
- end
- end
+ return
+ end
+
+ # discard local changes
+ `cd #{dirname} 2>&1 &&\
+ git reset HEAD --hard 2>&1 &&\
+ git checkout . 2>&1 &&\
+ git clean -fd 2>&1`
+
+ if lock = self.locks[seed.name]
+ lock_version = lock.version
+ lock_commit = lock.commit
+ end
+
+ if seed.version == lock_version and seed.commit == lock_commit
+ say "Using #{seed.name} (#{lock_version or lock_commit})"
+ return
+ end
+
+ if seed.version
+ say "Installing #{seed.name} #{seed.version}"\
+ " (was #{lock_version or lock_commit})".green
+ output = `cd #{dirname} 2>&1 &&\
+ git fetch origin #{seed.version} --tags 2>&1 &&\
+ git checkout #{seed.version} 2>&1`
+ puts output
+ if output.include?("Couldn't find")
+ say "[!] #{seed.name}: Couldn't find the tag or branch named "\
+ "`#{seed.commit}`.".red
+ end
+
+ elsif seed.commit
+ say "Installing #{seed.name} #{seed.commit}"\
+ " (was #{lock_version or lock_commit})".green
+ output = `cd #{dirname} 2>&1 &&
+ git checkout master 2>&1 &&
+ git pull 2>&1 &&
+ git checkout #{seed.commit} 2>&1`
+ if output.include?("did not match any")
+ say "[!] #{seed.name}: Couldn't find the commit "\
+ "`#{seed.commit}`.".red
end
end
+
end
# Append seed name as a prefix to file name and returns the path.
@@ -463,7 +529,7 @@ def configure_phase
def build_lockfile
tree = { "SEEDS" => [] }
self.seeds.each do |name, seed|
- tree["SEEDS"] << "#{name} (#{seed.version})"
+ tree["SEEDS"] << "#{name} (#{seed.version or '$' + seed.commit})"
end
File.write(self.lockfile_path, YAML.dump(tree))
end
diff --git a/lib/cocoaseeds/seed.rb b/lib/cocoaseeds/seed.rb
index 5a7eb0d..9c8f47c 100644
--- a/lib/cocoaseeds/seed.rb
+++ b/lib/cocoaseeds/seed.rb
@@ -9,6 +9,10 @@ class Seed
#
attr_accessor :version
+ # @return [String] the commit hash of the seed
+ #
+ attr_accessor :commit
+
# @return [String] the url of the seed
#
attr_accessor :url
diff --git a/test/test_install.rb b/test/test_install.rb
index ed8f820..dee43e3 100644
--- a/test/test_install.rb
+++ b/test/test_install.rb
@@ -2,7 +2,7 @@
class InstallTest < Test
- def test_install_github
+ def test_github_version
seedfile %{
github "devxoul/JLToast", "1.2.2", :files => "JLToast/*.{h,swift}"
}
@@ -14,6 +14,68 @@ def test_install_github
end
+ def test_github_commit_1
+ seedfile %{
+ github "devxoul/SwipeBack", :commit => "534a677"
+ }
+ @seed.install
+
+ dir = File.join(@seeds_dirname, "SwipeBack")
+
+ assert\
+ File.exists?(dir),
+ "Directory Seeds/SwipeBack not exists."
+
+ refute\
+ File.exists?(File.join(dir, "SwipeBack/SwipeBack.h")),
+ "File Seeds/SwipeBack/SwipeBack/SwipeBack.h should not exist."
+ end
+
+
+ def test_github_commit_2
+ seedfile %{
+ github "devxoul/SwipeBack", :commit => "90b256"
+ }
+ @seed.install
+
+ dir = File.join(@seeds_dirname, "SwipeBack")
+
+ assert\
+ File.exists?(dir),
+ "Directory Seeds/SwipeBack not exists."
+
+ assert\
+ File.exists?(File.join(dir, "SwipeBack/SwipeBack.h")),
+ "File Seeds/SwipeBack/SwipeBack/SwipeBack.h does not exist."
+ end
+
+
+ def test_github_update
+ path = File.join(@seeds_dirname, "SwiftyImage/SwiftyImage/SwiftyImage.h")
+
+ seedfile %{
+ github "devxoul/SwiftyImage", :commit => "af84dbd"
+ }
+ @seed.install
+ refute File.exists?(path),
+ "File Seeds/SwiftyImage/SwiftyImage/SwiftyImage.h should not exist."
+
+ seedfile %{
+ github "devxoul/SwiftyImage", :commit => "8b0c07a"
+ }
+ @seed.install
+ assert File.exists?(path),
+ "File Seeds/SwiftyImage/SwiftyImage/SwiftyImage.h does not exist."
+
+ seedfile %{
+ github "devxoul/SwiftyImage", :commit => "af84dbd"
+ }
+ @seed.install
+ refute File.exists?(path),
+ "File Seeds/SwiftyImage/SwiftyImage/SwiftyImage.h should not exist."
+ end
+
+
def test_raise_invalid_github_reponame
seedfile %{
github "JLToast", "1.2.2"
@@ -21,6 +83,14 @@ def test_raise_invalid_github_reponame
assert_raises Seeds::Exception do @seed.install end
end
+
+ def test_raise_github_both_tag_and_commit
+ seedfile %{
+ github "JLToast", "1.2.2", :commit => "83a1b50"
+ }
+ assert_raises Seeds::Exception do @seed.install end
+ end
+
end
@@ -45,4 +115,12 @@ def test_raise_invalid_bitbucket_reponame
assert_raises Seeds::Exception do @seed.install end
end
+
+ def test_raise_bitbucket_both_tag_and_commit
+ seedfile %{
+ bitbucket "JLToast", "1.2.2", :commit => "83a1b50"
+ }
+ assert_raises Seeds::Exception do @seed.install end
+ end
+
end
diff --git a/test/test_seed.rb b/test/test_seed.rb
index e7648d1..262fa09 100644
--- a/test/test_seed.rb
+++ b/test/test_seed.rb
@@ -15,6 +15,20 @@ def test_github_version
end
+ def test_github_commit
+ seedfile %{
+ github "devxoul/JLToast", :commit => "83a1b50153ed26f0ae0e90d65"
+ }
+ @seed.prepare_requirements
+ @seed.execute_seedfile
+ s = @seed.seeds["JLToast"]
+ assert_equal s.name, "JLToast"
+ assert_nil s.version
+ assert_equal s.commit, "83a1b50"
+ assert_equal s.url, "https://github.com/devxoul/JLToast"
+ end
+
+
def test_github_version_and_files
seedfile %{
github "devxoul/JLToast", "1.3.2", :files => "JLToast/*.{h,swift}"
@@ -44,6 +58,27 @@ def test_github_version_and_files_array
end
+ def test_github_commit_and_files
+ seedfile %{
+ github "devxoul/JLToast",
+ :commit => "83a1b50",
+ :files => "JLToast/*.{h,swift}"
+ }
+ @seed.prepare_requirements
+ @seed.execute_seedfile
+ s = @seed.seeds["JLToast"]
+ assert_equal s.name, "JLToast"
+ assert_nil s.version
+ assert_equal s.commit, "83a1b50"
+ assert_equal s.url, "https://github.com/devxoul/JLToast"
+ assert_equal s.files, ["JLToast/*.{h,swift}"]
+ end
+
+end
+
+
+class SeedTest
+
def test_bitbucket_version
seedfile %{
bitbucket "devxoul/JLToast", "1.3.2"
@@ -57,6 +92,20 @@ def test_bitbucket_version
end
+ def test_bitbucket_commit
+ seedfile %{
+ github "devxoul/JLToast", :commit => "83a1b50"
+ }
+ @seed.prepare_requirements
+ @seed.execute_seedfile
+ s = @seed.seeds["JLToast"]
+ assert_equal s.name, "JLToast"
+ assert_nil s.version
+ assert_equal s.commit, "83a1b50"
+ assert_equal s.url, "https://github.com/devxoul/JLToast"
+ end
+
+
def test_bitbucket_version_and_files
seedfile %{
bitbucket "devxoul/JLToast", "1.3.2", :files => "JLToast/*.{h,swift}"
@@ -85,4 +134,21 @@ def test_bitbucket_version_and_files_array
assert_equal s.files, ["JLToast/JLToast.h", "JLToast/JLToast.swift"]
end
+
+ def test_bitbucket_commit_and_files
+ seedfile %{
+ github "devxoul/JLToast",
+ :commit => "83a1b50",
+ :files => "JLToast/*.{h,swift}"
+ }
+ @seed.prepare_requirements
+ @seed.execute_seedfile
+ s = @seed.seeds["JLToast"]
+ assert_equal s.name, "JLToast"
+ assert_nil s.version
+ assert_equal s.commit, "83a1b50"
+ assert_equal s.url, "https://github.com/devxoul/JLToast"
+ assert_equal s.files, ["JLToast/*.{h,swift}"]
+ end
+
end