def install_seed(seed, dirname)
      # if remote url has changed, remove directory and clone again
      remote_url = `
        cd #{Shellwords.escape(dirname)} 2>&1 &&
        git remote show origin -n | grep Fetch | awk '{ print $3 }' 2>&1
      `.strip
      if remote_url != seed.url
        FileUtils.rm_rf(dirname)
      end

      # 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 += " #{Shellwords.escape(dirname)} 2>&1"
        output = `#{command}`

        unable_to_access = output.include?("unable to access")
        if unable_to_access and output.include?("Failed to connect to")
          raise Seeds::Exception.new\
            "#{seed.name}: Failed to connect to #{seed.url}. \n#{output}"
        end

        not_found = output.include?("not found")
        if not_found and output.include?("repository")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the repository."
        elsif not_found and output.include?("upstream")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the tag `#{seed.version}`."
        end

        if seed.commit and not seed.version # checkout to commit
          output = `cd #{Shellwords.escape(dirname)} 2>&1 &&\
                    git checkout #{seed.commit} 2>&1`
          if output.include?("did not match any")
            raise Seeds::Exception.new\
              "#{seed.name}: Couldn't find the commit `#{seed.commit}`."
          end
        end

        return
      end

      # discard local changes
      `cd #{Shellwords.escape(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 #{Shellwords.escape(dirname)} 2>&1 &&\
                 git fetch origin #{seed.version} --tags 2>&1 &&\
                 git checkout #{seed.version} 2>&1`
        if output.include?("Couldn't find")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the tag or branch `#{seed.version}`."
        end

      elsif seed.commit
        say "Installing #{seed.name} #{seed.commit}"\
            " (was #{lock_version or lock_commit})".green
        output = `cd #{Shellwords.escape(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")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the commit `#{seed.commit}`.".red
        end
      end

    end
def install_seed(seed, dirname)
      # if remote url has changed, remove directory and clone again
      remote_url = `
        cd #{Shellwords.escape(dirname)} 2>&1 &&
        git remote show origin -n | grep Fetch | awk '{ print $3 }' 2>&1
      `.strip
      if remote_url != seed.url
        FileUtils.rm_rf(dirname)
      end

      # 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 += " #{Shellwords.escape(dirname)} 2>&1"
        output = `#{command}`

        unable_to_access = output.include?("unable to access")
        if unable_to_access and output.include?("Failed to connect to")
          raise Seeds::Exception.new\
            "#{seed.name}: Failed to connect to #{seed.url}. \n#{output}"
        end

        not_found = output.include?("not found")
        if not_found and output.include?("repository")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the repository."
        elsif not_found and output.include?("upstream")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the tag `#{seed.version}`."
        end

        if seed.commit and not seed.version # checkout to commit
          output = `cd #{Shellwords.escape(dirname)} 2>&1 &&\
                    git checkout #{seed.commit} 2>&1`
          if output.include?("did not match any")
            raise Seeds::Exception.new\
              "#{seed.name}: Couldn't find the commit `#{seed.commit}`."
          end
        end

        return
      end

      # discard local changes
      `cd #{Shellwords.escape(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 #{Shellwords.escape(dirname)} 2>&1 &&\
                 git fetch origin #{seed.version} --tags 2>&1 &&\
                 git checkout #{seed.version} 2>&1`
        if output.include?("Couldn't find")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the tag or branch `#{seed.version}`."
        end

      elsif seed.commit
        say "Installing #{seed.name} #{seed.commit}"\
            " (was #{lock_version or lock_commit})".green
        output = `cd #{Shellwords.escape(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")
          raise Seeds::Exception.new\
            "#{seed.name}: Couldn't find the commit `#{seed.commit}`.".red
        end
      end

    end
Installs new seed or updates existing seed in {#dirname}.

 @!visibility private