roger 1.1.3 → 1.2.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 +4 -4
- data/.hound.yml +2 -0
- data/.rubocop.yml +47 -0
- data/.travis.yml +1 -5
- data/CHANGELOG.md +8 -0
- data/Gemfile +3 -3
- data/Rakefile +10 -4
- data/bin/roger +1 -1
- data/doc/mockupfile.md +97 -0
- data/doc/templating.md +5 -1
- data/examples/default_template/Gemfile +1 -1
- data/lib/roger/cli.rb +41 -36
- data/lib/roger/cli/command.rb +2 -4
- data/lib/roger/cli/generate.rb +1 -0
- data/lib/roger/cli/release.rb +2 -2
- data/lib/roger/cli/serve.rb +11 -11
- data/lib/roger/cli/test.rb +6 -5
- data/lib/roger/extractor.rb +42 -43
- data/lib/roger/generators.rb +27 -19
- data/lib/roger/generators/generator.rb +7 -10
- data/lib/roger/generators/new.rb +56 -41
- data/lib/roger/generators/templates/generator.tt +5 -5
- data/lib/roger/helpers/get_callable.rb +15 -14
- data/lib/roger/helpers/logging.rb +35 -13
- data/lib/roger/mockupfile.rb +13 -23
- data/lib/roger/project.rb +41 -34
- data/lib/roger/rack/roger.rb +28 -29
- data/lib/roger/rack/sleep.rb +4 -5
- data/lib/roger/release.rb +95 -72
- data/lib/roger/release/cleaner.rb +14 -13
- data/lib/roger/release/finalizers.rb +10 -10
- data/lib/roger/release/finalizers/dir.rb +17 -19
- data/lib/roger/release/finalizers/git_branch.rb +76 -38
- data/lib/roger/release/finalizers/rsync.rb +60 -49
- data/lib/roger/release/finalizers/zip.rb +32 -29
- data/lib/roger/release/injector.rb +43 -37
- data/lib/roger/release/processors.rb +24 -22
- data/lib/roger/release/processors/mockup.rb +97 -69
- data/lib/roger/release/processors/url_relativizer.rb +57 -30
- data/lib/roger/release/scm.rb +30 -27
- data/lib/roger/release/scm/git.rb +101 -92
- data/lib/roger/resolver.rb +86 -61
- data/lib/roger/server.rb +52 -27
- data/lib/roger/template.rb +102 -74
- data/lib/roger/test.rb +16 -13
- data/lib/roger/version.rb +3 -2
- data/roger.gemspec +9 -5
- data/test/helpers/cli.rb +17 -15
- data/test/project/Gemfile +2 -2
- data/test/project/html/formats/csv.rcsv +0 -0
- data/test/project/lib/generators/test.rb +2 -3
- data/test/project/lib/tests/fail/fail.rb +5 -6
- data/test/project/lib/tests/noop/lib/cli.rb +2 -1
- data/test/project/lib/tests/noop/lib/test.rb +5 -5
- data/test/project/lib/tests/noop/noop.rb +2 -1
- data/test/project/lib/tests/succeed/succeed.rb +5 -6
- data/test/unit/cli/cli_base_test.rb +2 -3
- data/test/unit/cli/cli_generate_test.rb +9 -10
- data/test/unit/cli/cli_serve_test.rb +22 -18
- data/test/unit/cli/cli_test_test.rb +13 -15
- data/test/unit/cli/cli_version_test.rb +4 -4
- data/test/unit/generators_test.rb +8 -10
- data/test/unit/helpers/logging_test.rb +64 -0
- data/test/unit/rack/roger_test.rb +21 -0
- data/test/unit/release/cleaner_test.rb +23 -19
- data/test/unit/release/finalizers/git_branch_test.rb +2 -1
- data/test/unit/release/finalizers/zip_test.rb +48 -0
- data/test/unit/release/mockup_test.rb +48 -0
- data/test/unit/release/processors_test.rb +19 -19
- data/test/unit/release_test.rb +15 -14
- data/test/unit/resolver_test.rb +21 -14
- data/test/unit/server_test.rb +31 -0
- data/test/unit/template_test.rb +58 -36
- data/test/unit/test_test.rb +3 -2
- metadata +35 -9
- data/test/Mockupfile-syntax.rb +0 -93
| @@ -1,47 +1,74 @@ | |
| 1 | 
            -
            require File.dirname(__FILE__) +  | 
| 1 | 
            +
            require File.dirname(__FILE__) + "../../../resolver"
         | 
| 2 2 |  | 
| 3 3 | 
             
            module Roger::Release::Processors
         | 
| 4 | 
            +
              # URL relativizer processor
         | 
| 5 | 
            +
              # The relativizer can be used to rewrite absolute paths in attributes to relative paths
         | 
| 6 | 
            +
              # during release.
         | 
| 4 7 | 
             
              class UrlRelativizer < Base
         | 
| 5 | 
            -
                
         | 
| 6 | 
            -
                def initialize(options={})
         | 
| 8 | 
            +
                def initialize(options = {})
         | 
| 7 9 | 
             
                  @options = {
         | 
| 8 | 
            -
                    : | 
| 9 | 
            -
                    : | 
| 10 | 
            -
                    : | 
| 10 | 
            +
                    url_attributes: %w(src href action),
         | 
| 11 | 
            +
                    match: ["**/*.html"],
         | 
| 12 | 
            +
                    skip: []
         | 
| 11 13 | 
             
                  }
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                  @options.update(options) if options | 
| 14 | 
            +
             | 
| 15 | 
            +
                  @options.update(options) if options
         | 
| 14 16 | 
             
                end
         | 
| 15 17 |  | 
| 16 | 
            -
                def call(release, options={})
         | 
| 18 | 
            +
                def call(release, options = {})
         | 
| 17 19 | 
             
                  options = {}.update(@options).update(options)
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                   | 
| 20 | 
            -
             | 
| 20 | 
            +
             | 
| 21 | 
            +
                  log_call(options)
         | 
| 22 | 
            +
             | 
| 21 23 | 
             
                  @resolver = Roger::Resolver.new(release.build_path)
         | 
| 22 | 
            -
             | 
| 24 | 
            +
             | 
| 25 | 
            +
                  relativize_attributes_in_files(
         | 
| 26 | 
            +
                    options[:url_attributes],
         | 
| 27 | 
            +
                    release.get_files(options[:match], options[:skip])
         | 
| 28 | 
            +
                  )
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                protected
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def log_call(options)
         | 
| 34 | 
            +
                  log_message = "Relativizing all URLS in #{options[:match].inspect}"
         | 
| 35 | 
            +
                  log_message << "files in attributes #{options[:url_attributes].inspect},"
         | 
| 36 | 
            +
                  log_message << "skipping #{options[:skip].any? ? options[:skip].inspect : 'none' }"
         | 
| 37 | 
            +
                  release.log(self, log_message)
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def relativize_attributes_in_files(attributes, files)
         | 
| 41 | 
            +
                  files.each do |file_path|
         | 
| 23 42 | 
             
                    release.debug(self, "Relativizing URLS in #{file_path}") do
         | 
| 24 | 
            -
                       | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 43 | 
            +
                      relativize_attributes_in_file(attributes, file_path)
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def relativize_attributes_in_file(attributes, file_path)
         | 
| 49 | 
            +
                  orig_source = File.read(file_path)
         | 
| 50 | 
            +
                  File.open(file_path, "w") do |f|
         | 
| 51 | 
            +
                    f.write(relativize_attributes_in_source(attributes, orig_source, file_path))
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def relativize_attributes_in_source(attributes, source, file_path)
         | 
| 56 | 
            +
                  doc = Hpricot(source)
         | 
| 57 | 
            +
                  attributes.each do |attribute|
         | 
| 58 | 
            +
                    (doc / "*[@#{attribute}]").each do |tag|
         | 
| 59 | 
            +
                      converted_url = @resolver.url_to_relative_url(tag[attribute], file_path)
         | 
| 60 | 
            +
                      release.debug(self, "Converting '#{tag[attribute]}' to '#{converted_url}'")
         | 
| 61 | 
            +
                      case converted_url
         | 
| 62 | 
            +
                      when String
         | 
| 63 | 
            +
                        tag[attribute] = converted_url
         | 
| 64 | 
            +
                      when nil
         | 
| 65 | 
            +
                        release.log(self, "Could not resolve link #{tag[attribute]} in #{file_path}")
         | 
| 40 66 | 
             
                      end
         | 
| 41 67 | 
             
                    end
         | 
| 42 68 | 
             
                  end
         | 
| 69 | 
            +
                  doc.to_original_html
         | 
| 43 70 | 
             
                end
         | 
| 44 71 | 
             
              end
         | 
| 45 72 | 
             
            end
         | 
| 46 73 |  | 
| 47 | 
            -
            Roger::Release::Processors.register(:url_relativizer, Roger::Release::Processors::UrlRelativizer)
         | 
| 74 | 
            +
            Roger::Release::Processors.register(:url_relativizer, Roger::Release::Processors::UrlRelativizer)
         | 
    
        data/lib/roger/release/scm.rb
    CHANGED
    
    | @@ -1,31 +1,34 @@ | |
| 1 | 
            -
            module Roger | 
| 2 | 
            -
              class  | 
| 3 | 
            -
                
         | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 1 | 
            +
            module Roger
         | 
| 2 | 
            +
              class Release
         | 
| 3 | 
            +
                module Scm
         | 
| 4 | 
            +
                  # Abstract SCM base class
         | 
| 5 | 
            +
                  class Base
         | 
| 6 | 
            +
                    attr_reader :config
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                    def initialize(config = {})
         | 
| 9 | 
            +
                      @config = config
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    # Returns the release version string from the SCM
         | 
| 13 | 
            +
                    #
         | 
| 14 | 
            +
                    # @return String The current version string
         | 
| 15 | 
            +
                    def version
         | 
| 16 | 
            +
                      fail "Implement in subclass"
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    # Returns the release version date from the SCM
         | 
| 20 | 
            +
                    def date
         | 
| 21 | 
            +
                      fail "Implement in subclass"
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    # Returns a Release::Scm object with the previous version's data
         | 
| 25 | 
            +
                    #
         | 
| 26 | 
            +
                    # @return Roger::Release::Scm The previous version
         | 
| 27 | 
            +
                    def previous
         | 
| 28 | 
            +
                      fail "Implement in subclass"
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 27 31 | 
             
                end
         | 
| 28 | 
            -
                
         | 
| 29 32 | 
             
              end
         | 
| 30 33 | 
             
            end
         | 
| 31 34 |  | 
| @@ -1,106 +1,115 @@ | |
| 1 | 
            -
            require  | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Roger | 
| 4 | 
            -
              class  | 
| 5 | 
            -
                
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                # Version is either:
         | 
| 14 | 
            -
                # - the tagged version number (first "v" will be stripped) or
         | 
| 15 | 
            -
                # - the return value of "git describe --tags HEAD"
         | 
| 16 | 
            -
                # - the short SHA1 if there hasn't been a previous tag
         | 
| 17 | 
            -
                def version
         | 
| 18 | 
            -
                  get_scm_data if @_version.nil?
         | 
| 19 | 
            -
                  @_version
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
                
         | 
| 22 | 
            -
                # Date will be Time.now if it can't be determined from GIT repository
         | 
| 23 | 
            -
                def date
         | 
| 24 | 
            -
                  get_scm_data if @_date.nil?
         | 
| 25 | 
            -
                  @_date
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
              
         | 
| 28 | 
            -
                def previous
         | 
| 29 | 
            -
                  self.class.new(@config.dup.update(:ref => get_previous_tag_name))
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
                
         | 
| 32 | 
            -
                protected
         | 
| 33 | 
            -
                
         | 
| 34 | 
            -
                def get_previous_tag_name
         | 
| 35 | 
            -
                  # Get list of SHA1 that have a ref
         | 
| 36 | 
            -
                  begin
         | 
| 37 | 
            -
                    sha1s = `git --git-dir=#{safe_git_dir} log --pretty='%H' --simplify-by-decoration`.split("\n")
         | 
| 38 | 
            -
                    tags = []
         | 
| 39 | 
            -
                    while tags.size < 2 && sha1s.any?
         | 
| 40 | 
            -
                      sha1 = sha1s.shift
         | 
| 41 | 
            -
                      tag = `git --git-dir=#{safe_git_dir} describe --tags --exact-match #{sha1} 2>/dev/null`.strip
         | 
| 42 | 
            -
                      tags << tag if !tag.empty?
         | 
| 1 | 
            +
            require "pathname"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Roger
         | 
| 4 | 
            +
              class Release
         | 
| 5 | 
            +
                module Scm
         | 
| 6 | 
            +
                  # The GIT SCM implementation for Roger release
         | 
| 7 | 
            +
                  class Git < Base
         | 
| 8 | 
            +
                    # @option config [String] :ref Ref to use for current tag
         | 
| 9 | 
            +
                    # @option config [String, Pathname] :path Path to working dir
         | 
| 10 | 
            +
                    def initialize(config = {})
         | 
| 11 | 
            +
                      super(config)
         | 
| 12 | 
            +
                      @config[:ref] ||= "HEAD"
         | 
| 43 13 | 
             
                    end
         | 
| 44 | 
            -
                    tags.last
         | 
| 45 | 
            -
                  rescue
         | 
| 46 | 
            -
                    raise "Could not get previous tag"
         | 
| 47 | 
            -
                  end      
         | 
| 48 | 
            -
                end
         | 
| 49 | 
            -
                
         | 
| 50 | 
            -
                def git_dir
         | 
| 51 | 
            -
                  @git_dir ||= find_git_dir(@config[:path])
         | 
| 52 | 
            -
                end
         | 
| 53 14 |  | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 15 | 
            +
                    # Version is either:
         | 
| 16 | 
            +
                    # - the tagged version number (first "v" will be stripped) or
         | 
| 17 | 
            +
                    # - the return value of "git describe --tags HEAD"
         | 
| 18 | 
            +
                    # - the short SHA1 if there hasn't been a previous tag
         | 
| 19 | 
            +
                    def version
         | 
| 20 | 
            +
                      get_scm_data if @_version.nil?
         | 
| 21 | 
            +
                      @_version
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    # Date will be Time.now if it can't be determined from GIT repository
         | 
| 25 | 
            +
                    def date
         | 
| 26 | 
            +
                      get_scm_data if @_date.nil?
         | 
| 27 | 
            +
                      @_date
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def previous
         | 
| 31 | 
            +
                      self.class.new(@config.dup.update(ref: get_previous_tag_name))
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    protected
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    def get_previous_tag_name
         | 
| 37 | 
            +
                      # Get list of SHA1 that have a ref
         | 
| 38 | 
            +
                      sha1s = `git --git-dir=#{safe_git_dir} log --pretty='%H' --simplify-by-decoration`
         | 
| 39 | 
            +
                      sha1s = sha1s.split("\n")
         | 
| 40 | 
            +
                      tags = []
         | 
| 41 | 
            +
                      while tags.size < 2 && sha1s.any?
         | 
| 42 | 
            +
                        sha1 = sha1s.shift
         | 
| 43 | 
            +
                        tag = `git --git-dir=#{safe_git_dir} describe --tags --exact-match #{sha1} 2>/dev/null`
         | 
| 44 | 
            +
                        tag = tag.strip
         | 
| 45 | 
            +
                        tags << tag unless tag.empty?
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                      tags.last
         | 
| 48 | 
            +
                    rescue
         | 
| 49 | 
            +
                      raise "Could not get previous tag"
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    def git_dir
         | 
| 53 | 
            +
                      @git_dir ||= find_git_dir(@config[:path])
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    # Safely escaped git dir
         | 
| 57 | 
            +
                    def safe_git_dir
         | 
| 58 | 
            +
                      Shellwords.escape(git_dir.to_s)
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    # Preload version control data.
         | 
| 62 | 
            +
                    def get_scm_data(ref = @config[:ref])
         | 
| 63 | 
            +
                      @_version = scm_version(ref) || ""
         | 
| 64 | 
            +
                      @_date = scm_date(ref) || Time.now
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    # Some hackery to determine if ref is on a tagged version or not
         | 
| 68 | 
            +
                    # @return [String, nil] Will return version number if available, nil otherwise
         | 
| 69 | 
            +
                    def scm_version(ref)
         | 
| 70 | 
            +
                      return nil unless File.exist?(git_dir)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                      version = `git --git-dir=#{safe_git_dir} describe --tags #{ref} 2>&1`
         | 
| 58 73 |  | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
                  @_date = Time.now
         | 
| 63 | 
            -
                  begin
         | 
| 64 | 
            -
                    if File.exist?(git_dir)
         | 
| 65 | 
            -
                      @_version = `git --git-dir=#{safe_git_dir} describe --tags #{ref} 2>&1`
         | 
| 66 | 
            -
                      
         | 
| 67 | 
            -
                      if $?.to_i > 0
         | 
| 68 | 
            -
                        # HEAD is not a tagged verison, get the short SHA1 instead            
         | 
| 69 | 
            -
                        @_version = `git --git-dir=#{safe_git_dir} show #{ref} --format=format:"%h" -s 2>&1` 
         | 
| 74 | 
            +
                      if $CHILD_STATUS.to_i > 0
         | 
| 75 | 
            +
                        # HEAD is not a tagged version, get the short SHA1 instead
         | 
| 76 | 
            +
                        version = `git --git-dir=#{safe_git_dir} show #{ref} --format=format:"%h" -s 2>&1`
         | 
| 70 77 | 
             
                      else
         | 
| 71 78 | 
             
                        # HEAD is a tagged version, if version is prefixed with "v" it will be stripped off
         | 
| 72 | 
            -
                         | 
| 79 | 
            +
                        version.gsub!(/^v/, "")
         | 
| 73 80 | 
             
                      end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 81 | 
            +
             | 
| 82 | 
            +
                      version.strip!
         | 
| 83 | 
            +
                    rescue RuntimeError
         | 
| 84 | 
            +
                      nil
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                    # Get date of ref from git
         | 
| 88 | 
            +
                    # @return [Time, nil] Returns time if available and parseable, nil otherwise
         | 
| 89 | 
            +
                    def scm_date(ref)
         | 
| 90 | 
            +
                      return nil unless File.exist?(git_dir)
         | 
| 91 | 
            +
             | 
| 76 92 | 
             
                      # Get the date in epoch time
         | 
| 77 93 | 
             
                      date = `git --git-dir=#{safe_git_dir} show #{ref} --format=format:"%ct" -s 2>&1`
         | 
| 78 | 
            -
                      if date =~ /\d+/
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                       | 
| 81 | 
            -
                        @_date = Time.now
         | 
| 82 | 
            -
                      end
         | 
| 83 | 
            -
                
         | 
| 94 | 
            +
                      Time.at(date.to_i) if date =~ /\d+/
         | 
| 95 | 
            +
                    rescue RuntimeError
         | 
| 96 | 
            +
                      nil
         | 
| 84 97 | 
             
                    end
         | 
| 85 | 
            -
                  rescue RuntimeError => e
         | 
| 86 | 
            -
                  end
         | 
| 87 98 |  | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
                    path = path.parent
         | 
| 95 | 
            -
                  end
         | 
| 96 | 
            -
                  
         | 
| 97 | 
            -
                  path = path + ".git"
         | 
| 98 | 
            -
                  
         | 
| 99 | 
            -
                  raise "Could not find suitable .git dir in #{path}" if !path.directory?
         | 
| 99 | 
            +
                    # Find the git dir
         | 
| 100 | 
            +
                    def find_git_dir(path)
         | 
| 101 | 
            +
                      path = Pathname.new(path).realpath
         | 
| 102 | 
            +
                      while path.parent != path && !(path + ".git").directory?
         | 
| 103 | 
            +
                        path = path.parent
         | 
| 104 | 
            +
                      end
         | 
| 100 105 |  | 
| 101 | 
            -
             | 
| 106 | 
            +
                      path += ".git"
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                      fail "Could not find suitable .git dir in #{path}" unless path.directory?
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                      path
         | 
| 111 | 
            +
                    end
         | 
| 112 | 
            +
                  end
         | 
| 102 113 | 
             
                end
         | 
| 103 | 
            -
                
         | 
| 104 114 | 
             
              end
         | 
| 105 115 | 
             
            end
         | 
| 106 | 
            -
             | 
    
        data/lib/roger/resolver.rb
    CHANGED
    
    | @@ -1,92 +1,72 @@ | |
| 1 1 | 
             
            module Roger
         | 
| 2 | 
            +
              # The resolver is here to resolve urls to paths and sometimes vice-versa
         | 
| 2 3 | 
             
              class Resolver
         | 
| 3 | 
            -
             | 
| 4 4 | 
             
                attr_reader :load_paths
         | 
| 5 | 
            -
             | 
| 5 | 
            +
             | 
| 6 6 | 
             
                def initialize(paths)
         | 
| 7 | 
            -
                   | 
| 7 | 
            +
                  fail ArgumentError, "Resolver base path can't be nil" if paths.nil?
         | 
| 8 8 |  | 
| 9 9 | 
             
                  # Convert to paths
         | 
| 10 | 
            -
                  @load_paths = [paths].flatten.map{|p| Pathname.new(p) }
         | 
| 10 | 
            +
                  @load_paths = [paths].flatten.map { |p| Pathname.new(p) }
         | 
| 11 11 | 
             
                end
         | 
| 12 | 
            -
             | 
| 12 | 
            +
             | 
| 13 13 | 
             
                # @param [String] url The url to resolve to a path
         | 
| 14 14 | 
             
                # @param [Hash] options Options
         | 
| 15 15 | 
             
                #
         | 
| 16 | 
            -
                # @option options [true,false] :exact_match Wether or not to match exact paths, | 
| 17 | 
            -
                #  | 
| 16 | 
            +
                # @option options [true,false] :exact_match Wether or not to match exact paths,
         | 
| 17 | 
            +
                #   this is mainly used in the path_to_url method to match .js, .css, etc files.
         | 
| 18 | 
            +
                # @option options [String] :preferred_extension The part to chop off
         | 
| 19 | 
            +
                #   and re-add to search for more complex double-extensions. (Makes it possible to have context
         | 
| 20 | 
            +
                #   aware partials)
         | 
| 18 21 | 
             
                def find_template(url, options = {})
         | 
| 19 | 
            -
                  orig_path, qs, anch = strip_query_string_and_anchor(url.to_s)
         | 
| 20 | 
            -
             | 
| 21 22 | 
             
                  options = {
         | 
| 22 | 
            -
                    : | 
| 23 | 
            -
                    : | 
| 23 | 
            +
                    exact_match: false,
         | 
| 24 | 
            +
                    preferred_extension: "html"
         | 
| 24 25 | 
             
                  }.update(options)
         | 
| 25 26 |  | 
| 26 | 
            -
                   | 
| 27 | 
            -
              
         | 
| 28 | 
            -
                  paths.find do |path|
         | 
| 29 | 
            -
                    if options[:exact_match] && File.exist?(path)
         | 
| 30 | 
            -
                      return Pathname.new(path)
         | 
| 31 | 
            -
                    end      
         | 
| 32 | 
            -
                    
         | 
| 33 | 
            -
                    # It's a directory, add "/index"
         | 
| 34 | 
            -
                    if File.directory?(path)
         | 
| 35 | 
            -
                      path = File.join(path, "index")
         | 
| 36 | 
            -
                    end
         | 
| 37 | 
            -
                    
         | 
| 38 | 
            -
                    # 2. If it's preferred_extension, we strip of the extension
         | 
| 39 | 
            -
                    if path =~ /\.#{options[:preferred_extension]}\Z/
         | 
| 40 | 
            -
                      path.sub!(/\.#{options[:preferred_extension]}\Z/, "")
         | 
| 41 | 
            -
                    end
         | 
| 42 | 
            -
                    
         | 
| 43 | 
            -
                    extensions = Tilt.default_mapping.template_map.keys + Tilt.default_mapping.lazy_map.keys
         | 
| 27 | 
            +
                  orig_path, _qs, _anch = strip_query_string_and_anchor(url.to_s)
         | 
| 44 28 |  | 
| 45 | 
            -
             | 
| 46 | 
            -
                    extensions += extensions.map{|ext| "#{options[:preferred_extension]}.#{ext}"}
         | 
| 29 | 
            +
                  output = nil
         | 
| 47 30 |  | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                    end
         | 
| 31 | 
            +
                  load_paths.find do |load_path|
         | 
| 32 | 
            +
                    path = File.join(load_path, orig_path)
         | 
| 51 33 |  | 
| 52 | 
            -
                     | 
| 34 | 
            +
                    # If it's an exact match we're done
         | 
| 35 | 
            +
                    if options[:exact_match] && File.exist?(path)
         | 
| 36 | 
            +
                      output = Pathname.new(path)
         | 
| 37 | 
            +
                    else
         | 
| 38 | 
            +
                      output = find_file_with_extension(path, options[:preferred_extension])
         | 
| 39 | 
            +
                    end
         | 
| 53 40 | 
             
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  output
         | 
| 54 43 | 
             
                end
         | 
| 55 | 
            -
                 | 
| 56 | 
            -
             | 
| 57 | 
            -
                
         | 
| 44 | 
            +
                alias_method :url_to_path, :find_template
         | 
| 45 | 
            +
             | 
| 58 46 | 
             
                # Convert a disk path on file to an url
         | 
| 59 47 | 
             
                def path_to_url(path, relative_to = nil)
         | 
| 60 | 
            -
             | 
| 61 48 | 
             
                  # Find the parent path we're in
         | 
| 62 49 | 
             
                  path = Pathname.new(path).realpath
         | 
| 63 | 
            -
                  base =  | 
| 50 | 
            +
                  base = load_paths.find { |lp| path.to_s =~ /\A#{Regexp.escape(lp.realpath.to_s)}/ }
         | 
| 64 51 |  | 
| 65 52 | 
             
                  path = path.relative_path_from(base).cleanpath
         | 
| 66 | 
            -
             | 
| 53 | 
            +
             | 
| 67 54 | 
             
                  if relative_to
         | 
| 68 | 
            -
                     | 
| 69 | 
            -
                      relative_to = Pathname.new(File.dirname(relative_to.to_s)).relative_path_from(base).cleanpath
         | 
| 70 | 
            -
                    else
         | 
| 71 | 
            -
                      relative_to = Pathname.new(File.dirname(relative_to.to_s))
         | 
| 72 | 
            -
                    end
         | 
| 73 | 
            -
                    path = Pathname.new("/" + path.to_s).relative_path_from(Pathname.new("/" + relative_to.to_s))
         | 
| 74 | 
            -
                    path.to_s
         | 
| 55 | 
            +
                    relative_path_to_url(path, relative_to, base).to_s
         | 
| 75 56 | 
             
                  else
         | 
| 76 | 
            -
                    " | 
| 57 | 
            +
                    "/#{path}"
         | 
| 77 58 | 
             
                  end
         | 
| 78 | 
            -
                  
         | 
| 79 59 | 
             
                end
         | 
| 80 | 
            -
             | 
| 60 | 
            +
             | 
| 81 61 | 
             
                def url_to_relative_url(url, relative_to_path)
         | 
| 82 62 | 
             
                  # Skip if the url doesn't start with a / (but not with //)
         | 
| 83 | 
            -
                  return false unless url =~  | 
| 84 | 
            -
             | 
| 63 | 
            +
                  return false unless url =~ %r{\A/[^/]}
         | 
| 64 | 
            +
             | 
| 85 65 | 
             
                  path, qs, anch = strip_query_string_and_anchor(url)
         | 
| 86 66 |  | 
| 87 67 | 
             
                  # Get disk path
         | 
| 88 | 
            -
                  if true_path =   | 
| 89 | 
            -
                    path =  | 
| 68 | 
            +
                  if true_path =  url_to_path(path, exact_match: true)
         | 
| 69 | 
            +
                    path = path_to_url(true_path, relative_to_path)
         | 
| 90 70 | 
             
                    path += qs if qs
         | 
| 91 71 | 
             
                    path += anch if anch
         | 
| 92 72 | 
             
                    path
         | 
| @@ -94,26 +74,71 @@ module Roger | |
| 94 74 | 
             
                    false
         | 
| 95 75 | 
             
                  end
         | 
| 96 76 | 
             
                end
         | 
| 97 | 
            -
             | 
| 77 | 
            +
             | 
| 98 78 | 
             
                def strip_query_string_and_anchor(url)
         | 
| 99 79 | 
             
                  url = url.dup
         | 
| 100 | 
            -
             | 
| 80 | 
            +
             | 
| 101 81 | 
             
                  # Strip off anchors
         | 
| 102 82 | 
             
                  anchor = nil
         | 
| 103 83 | 
             
                  url.gsub!(/(#.+)\Z/) do |r|
         | 
| 104 84 | 
             
                    anchor = r
         | 
| 105 85 | 
             
                    ""
         | 
| 106 86 | 
             
                  end
         | 
| 107 | 
            -
             | 
| 87 | 
            +
             | 
| 108 88 | 
             
                  # Strip off query strings
         | 
| 109 89 | 
             
                  query = nil
         | 
| 110 90 | 
             
                  url.gsub!(/(\?.+)\Z/) do |r|
         | 
| 111 91 | 
             
                    query = r
         | 
| 112 92 | 
             
                    ""
         | 
| 113 93 | 
             
                  end
         | 
| 114 | 
            -
             | 
| 94 | 
            +
             | 
| 115 95 | 
             
                  [url, query, anchor]
         | 
| 116 | 
            -
                end | 
| 117 | 
            -
             | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                protected
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                # Tries all extensions on path to see what file exists
         | 
| 101 | 
            +
                # @return [Pathname,nil] returns a pathname of the full file path if found. nil otherwise
         | 
| 102 | 
            +
                def find_file_with_extension(path, preferred_extension)
         | 
| 103 | 
            +
                  output = nil
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  file_path = path
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  # If it's a directory, add "/index"
         | 
| 108 | 
            +
                  file_path = File.join(file_path, "index") if File.directory?(file_path)
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  # Strip of extension
         | 
| 111 | 
            +
                  if path =~ /\.#{preferred_extension}\Z/
         | 
| 112 | 
            +
                    file_path.sub!(/\.#{preferred_extension}\Z/, "")
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  possible_extensions(preferred_extension).find do |ext|
         | 
| 116 | 
            +
                    path_with_extension = file_path + "." + ext
         | 
| 117 | 
            +
                    if File.exist?(path_with_extension)
         | 
| 118 | 
            +
                      output = Pathname.new(path_with_extension)
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                  output
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                # Makes a list of all Tilt extensions
         | 
| 125 | 
            +
                # Also adds a list of double extensions. Example:
         | 
| 126 | 
            +
                # tilt_extensions = %w(erb md); second_extension = "html"
         | 
| 127 | 
            +
                # return %w(erb md html.erb html.md)
         | 
| 128 | 
            +
                def possible_extensions(second_extension)
         | 
| 129 | 
            +
                  extensions = Tilt.default_mapping.template_map.keys + Tilt.default_mapping.lazy_map.keys
         | 
| 130 | 
            +
                  extensions + extensions.map { |ext| "#{second_extension}.#{ext}" }
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                def relative_path_to_url(path, relative_to, base)
         | 
| 134 | 
            +
                  relative_to = Pathname.new(File.dirname(relative_to.to_s))
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                  # If relative_to is an absolute path
         | 
| 137 | 
            +
                  if relative_to.to_s =~ %r{\A/}
         | 
| 138 | 
            +
                    relative_to = relative_to.relative_path_from(base).cleanpath
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                  Pathname.new("/" + path.to_s).relative_path_from(Pathname.new("/" + relative_to.to_s))
         | 
| 142 | 
            +
                end
         | 
| 118 143 | 
             
              end
         | 
| 119 144 | 
             
            end
         |