Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The usage of "ptools" seems to break the "build" function of middleman on Windows #62

Closed
whitetrefoil opened this issue Apr 21, 2014 · 18 comments

Comments

@whitetrefoil
Copy link
Contributor

My ruby skill is not good enough so I came here to look for help.

I'm now using middleman-deploy (0.2.3) with middleman (3.3.2) & ptools (1.2.4-x86-mingw32).

When trying to build the console throws:

E:/usr/local/Ruby/lib/ruby/2.0.0/pathname.rb:47:in `[]': no implicit conversion from nil to integer (TypeError)
        from E:/usr/local/Ruby/lib/ruby/2.0.0/pathname.rb:47:in `chop_basename'
        from E:/usr/local/Ruby/lib/ruby/2.0.0/pathname.rb:102:in `cleanpath_aggressive'
        from E:/usr/local/Ruby/lib/ruby/2.0.0/pathname.rb:90:in `cleanpath'
        from E:/usr/local/Ruby/lib/ruby/2.0.0/pathname.rb:486:in `relative_path_from'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/middleman-core-3.3.2/lib/middleman-core/cli/build.rb:193:in `execute!'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/middleman-core-3.3.2/lib/middleman-core/cli/build.rb:128:in `invoke!'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/actions.rb:94:in `action'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/middleman-core-3.3.2/lib/middleman-core/cli/build.rb:70:in `build'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/command.rb:27:in `run'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/invocation.rb:126:in `invoke_command'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor.rb:359:in `dispatch'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/base.rb:440:in `start'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/middleman-core-3.3.2/lib/middleman-core/cli.rb:76:in `method_missing'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/command.rb:29:in `run'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/command.rb:126:in `run'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/invocation.rb:126:in `invoke_command'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor.rb:359:in `dispatch'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/thor-0.19.1/lib/thor/base.rb:440:in `start'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/middleman-core-3.3.2/lib/middleman-core/cli.rb:22:in `start'
        from E:/usr/local/Ruby/lib/ruby/gems/2.0.0/gems/middleman-core-3.3.2/bin/middleman:18:in `<top (required)>'
        from E:/usr/local/Ruby/bin/middleman:23:in `load'
        from E:/usr/local/Ruby/bin/middleman:23:in `<main>'

I traced to E:/usr/local/Ruby/lib/ruby/2.0.0/pathname.rb:43:

base = File.basename(path)

And at the final moment between crach, the result of File.basename became wired.

Before required ptools, File.basename 'E:/' returns "/" and everything was good.

After required ptools, File.basename 'E:/' returns "E:\\", then cause the cause the following codes crashed:

    if /\A#{SEPARATOR_PAT}?\z/o =~ base
      return nil
    else
      return path[0, path.rindex(base)], base
    end

I know nor whether this is a bug or a 'by design' for ptools, nor whether this is expected for middleman-deploy, nor whether there will be another solution to get it work. Is there anybody can help?

Thanks

@whitetrefoil
Copy link
Contributor Author

I talked to the author of ptools, and he told me that this behavior in ptools is by design. And it's not ptools who changes this behavior but win32/file.

@djberg96
Copy link

If you can tell me what that if-clause is trying to do generally, maybe I can help you with a better solution.

@whitetrefoil
Copy link
Contributor Author

@djberg96 Thanks for your help! But I haven't started to look into those logics. Instead, I'm looking at what from ptools is used in this gem. Seems only File.binary?().

@whitetrefoil
Copy link
Contributor Author

I guess I've found the problem...

The final moment before crash in middleman is at middleman-core-3.3.2/lib/middleman-core/cli/build.rb:193:

(@source_dir + @app.images_dir).relative_path_from(@app.root_path)

Here, the @source_dir comes from middleman-core-3.3.2/lib/middleman-core/application.rb:214:

    def source_dir
      File.join(root, config[:source])
    end

which is parsed by File.join.

While the @app.root_path comes from middleman-core-3.3.2/lib/middleman-core/application.rb:59:

    def self.root
      ENV['MM_ROOT'] || Dir.pwd
    end
    delegate :root, :to => :"self.class"

    # Pathname-addressed root
    def self.root_path
      Pathname(root)
    end

which is un-parsed.

Both variables are {Pathname}.

When executed without win32/file, both variables were using /. But when we required win32/file, the @source_dir became with \ while the @app.root_path was still with /. And the #relative_path_from of {Pathname} does not allow comparing paths with different separators.

This is tricky... Because middleman itself does not using win32/file. I don't think that we can say it's a bug of middleman. But at middleman-deploy side, I don't know how to deal with it.

@whitetrefoil
Copy link
Contributor Author

I tried to override @source_dir or @app.root_path but failed because of this lines:

# middleman-core-3.3.2/lib/middleman-core/cli/build.rb:206
if @build_dir.expand_path.relative_path_from(@source_dir).to_s =~ /\A[.\/]+\Z/

The pathname lib behave differently in different methods after required win32/file.

Some methods like + will convert / to \, but #expand_path always returns path with '/' no matter win32/file is required or not.

More important, Pathname#relative_path_from always crash if the path is with '/' when win32/file is required.

I'll try these possible solutions tomorrow if I have time, but I don't believe any of them will be a good solution, at best a workaround:

  1. Remove ptools from ftp.rb & sftp.rb, then find another substitute to provide File#binary?
  2. Overrides a part of what win32/file has overrided back.
  3. Overrides some methods of ruby's Pathname class.

Is there any expert can help? 😿

@djberg96
Copy link

What happens if you install and require the pathname2 gem?

@whitetrefoil
Copy link
Contributor Author

It crashed because pathname2 let Pathname#join() to return a string instead of a new Pathname.

@whitetrefoil
Copy link
Contributor Author

There are too many codes in middleman are using plain string to process paths which conflicts win32/file...

# e.g.
base_path = path.sub("#{load_path}/", '')
# or
if load_path.end_with?('/images')

@djberg96
Copy link

This is something I wouldn't do:

if load_path.end_with?('/images')

Instead:

if File.basename(load_path) == 'images'

Using String#sub to mangle paths is a bad idea in general. With respect, I think maybe some refactoring is in order.

@djberg96
Copy link

Hm, maybe I need to updated the pathname2 gem then. Arguably a bug.

@djberg96
Copy link

I updated the pathname2 gem at least so that Pathname#join and Pathname#expand_path now return Pathname objects.

@whitetrefoil
Copy link
Contributor Author

@djberg96 Tried pathname2 =1.7.2. This time bundler-1.6.2/lib/bundler.rb:192 crashed:

def root
  default_gemfile.dirname.expand_path
end

Cause is Pathname#dirname returns plain string in some case:

require 'pathname'
puts Pathname.new('D:/asdf/qwert').dirname.expand_path
# => D:/asdf
require 'pathname2'
puts Pathname.new('D:/asdf/qwert').dirname.expand_path
# => undefined method `expand_path' for "D:\\asdf":String (NoMethodError)

@djberg96
Copy link

Ok, both basename and dirname have been updated to return Pathname objects in 1.7.3.

@tvaughan
Copy link
Contributor

Does anything need to happen to middleman deploy so that it picks up these updates?

@maunovaha
Copy link

I am currently facing the same issue, darn. Did @whitetrefoil solve this somehow eventually? or resolved to use some other gem? Hence, if the problem is all the way inside middleman-core - I believe that we can't get this solved here, or can we?

My setup is: middleman-deploy (0.2.4), middleman (3.3.3) and ptools (1.2.4 universal-mingw32)

@djberg96
Copy link

Is this still a problem since I've update pathname2?

@djberg96
Copy link

@whitetrefoil Any luck?

@whitetrefoil
Copy link
Contributor Author

@djberg96 oops... Sorry, I didn't see your previous message. I haven't written ruby for years, and I can't remember details of this issue. I need some time to catch up.

I guess we can close this issue. If there's still problem we can just reopen it.😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants