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

Ignore broken symlinks in mkdocs serve. #639

Closed
paulproteus opened this Issue Jun 18, 2015 · 7 comments

Comments

Projects
None yet
4 participants
@paulproteus

paulproteus commented Jun 18, 2015

What I am experiencing:

  • When I am editing index.md in Emacs, Emacs creates files like:
➜  docs git:(master) ✗ ls -al .#*  
lrwxrwxrwx 1 paulproteus paulproteus 36 Jun 17 17:24 .#index.md -> paulproteus@charkha.27783:1434311808
  • These files are Emacs' way of using symlinks to track which computer+process was Emacs-ing the file, so that in case of a crash, Emacs can figure out how to restore its state.

What I expect:

  • When I edit somethingelse.md and press save, I expect the mkdocs livereload to reload the browser.

What I see instead:

INFO    -  Building documentation... 
ERROR   -  file not found: /home/paulproteus/projects/sandstorm/docs/.#index.md 
ERROR   -  Error building page .#index.md 
[E 150617 17:22:21 ioloop:612] Exception in callback (3, <function null_wrapper at 0x7fc883190500>)
    Traceback (most recent call last):
      File "/home/paulproteus/.local/lib/python2.7/site-packages/tornado/ioloop.py", line 866, in start
        handler_func(fd_obj, events)
      File "/home/paulproteus/.local/lib/python2.7/site-packages/tornado/stack_context.py", line 275, in null_wrapper
        return fn(*args, **kwargs)
      File "/usr/lib/python2.7/dist-packages/pyinotify.py", line 1604, in handle_read
        self.process_events()
      File "/usr/lib/python2.7/dist-packages/pyinotify.py", line 1321, in process_events
        self._default_proc_fun(revent)
      File "/home/paulproteus/.local/lib/python2.7/site-packages/livereload/watcher.py", line 152, in inotify_event
        self.callback()
      File "/home/paulproteus/.local/lib/python2.7/site-packages/livereload/handlers.py", line 65, in poll_tasks
        filepath, delay = cls.watcher.examine()
      File "/home/paulproteus/.local/lib/python2.7/site-packages/livereload/watcher.py", line 72, in examine
        func and func()
      File "/usr/lib/python2.7/dist-packages/mkdocs/serve.py", line 74, in builder
        build(config, live_server=True)
      File "/usr/lib/python2.7/dist-packages/mkdocs/build.py", line 299, in build
        build_pages(config)
      File "/usr/lib/python2.7/dist-packages/mkdocs/build.py", line 259, in build_pages
        dump_json)
      File "/usr/lib/python2.7/dist-packages/mkdocs/build.py", line 171, in _build_page
        input_content = io.open(input_path, 'r', encoding='utf-8').read()
    IOError: [Errno 2] No such file or directory: '/home/paulproteus/projects/sandstorm/docs/.#index.md'

What I propose:

  • If a "No such file or directory" error occurs, but the problem is a broken symlink, the mkdocs build should continue as if the file does not exist. Note that this arguably is a special-case to handle Emacs' own weirdness; a different way to do it would be to look at the list of git ignored files.
  • Perhaps in general, mkdocs should issue a warning (not an error) on broken symlinks, gracefully ignoring them.

I'm open to a bunch of ideas. I wanted to file this in the hopes of sparking a discussion where the maintainers of mkdocs could express their opinion about the best way forward.

Thanks so much! Also hi! I'm twitter.com/asheeshlaroia and was chatting with a mkdocs developer earlier today. Seems like a great project! I learned about it via http://ericholscher.com/blog/2014/feb/27/how-i-judge-documentation-quality/ !

@d0ugal d0ugal added the Bug label Jun 18, 2015

@d0ugal

This comment has been minimized.

Member

d0ugal commented Jun 18, 2015

Interesting, I think we will want to add an extra check in the file discovery to check is the file is a symlink and then check that the target is valid. If it isn't we can ignore it. We can probably do this with a combination of os.path.islink and os.readlink.

@d0ugal d0ugal changed the title from Feature request: For livereload, ignore broken symlinks to Ignore broken symlinks in mkdocs serve. Jun 27, 2015

@d0ugal d0ugal added this to the 0.15.0 milestone Jun 27, 2015

d0ugal added a commit to d0ugal/mkdocs that referenced this issue Jun 27, 2015

d0ugal added a commit that referenced this issue Jun 28, 2015

@d0ugal d0ugal closed this in #668 Jun 28, 2015

@paulproteus

This comment has been minimized.

paulproteus commented Jun 29, 2015

@d0ugal

This comment has been minimized.

Member

d0ugal commented Jun 29, 2015

Happy to help :)

@ky4n

This comment has been minimized.

ky4n commented Feb 17, 2016

First I'd like to point out that I like this project quite much and currently implement mkdocs for our internal repository.

Unfortunately I've stumbled on an issue caused by the way this bugfix handles symbolic links. It looks like symbolic links with relative path are not processed properly.

Sample tree (lets assume path /srv/git/repo:

docs
├── foobar.md -> foobar/README.md
├── foobaz.md -> ../cookbooks/foobaz/README.md
├── Test.md
├── index.md
└── foobaz
    ├── index.md
    └── README.md

Neither docs/foobar.md nor docs/foobaz.md will be built/served (assuming no pages listed in the config file). walk_docs_dir from config/config_options.py is having some issues with parsing the symlinks.

It looks like this happens because the CWD is different from dirpath. In my example it's dirpath: /srv/git/repo and cwd was /srv/git/repo/docs, which makes mkdocs ignore those 2 files despite they being valid symlinks.

Diff for config/config_options.py:

@@ -352,7 +349,8 @@
                 # Some editors (namely Emacs) will create temporary symlinks
                 # for internal magic. We can just ignore these files.
                 if os.path.islink(fullpath):
-                    if not os.path.exists(os.readlink(fullpath)):
+                    fp = os.path.join(dirpath, os.readlink(fullpath))
+                    if not os.path.exists(fp):
                         continue

                 relpath = os.path.normpath(os.path.relpath(fullpath, docs_dir))

This could be probably written a bit nicer so I'm just pasting the diff here.

PS. I'm using mkdocs installed via pip if that matters (ver 0.15.2)

@waylan

This comment has been minimized.

Member

waylan commented Feb 17, 2016

@ky4n this sounds like a legitimate issue with a reasonable solution. Unfortunately, you risk it getting forgotten as you commented on a closed issue. It would have been better to create a new issue which links to this one for context. Actually, as you have a provided fix, a pull request would be the quickest way to have the fix applied.

@d0ugal d0ugal reopened this Feb 17, 2016

d0ugal added a commit to d0ugal/mkdocs that referenced this issue Feb 17, 2016

@d0ugal d0ugal removed this from the 0.15.0 milestone Feb 18, 2016

d0ugal added a commit to d0ugal/mkdocs that referenced this issue Feb 18, 2016

@d0ugal d0ugal closed this in #827 Feb 18, 2016

@d0ugal

This comment has been minimized.

@ky4n

This comment has been minimized.

ky4n commented Feb 23, 2016

@d0ugal Thank you, works like a charm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment