#pragma section-numbers 2 <> = Path separator handling = How Mercurial handles path separators <> == Overview == This page is intended to collect information about Mercurial's current path separator behavior and help formulate coherent rules for when paths should be converted. == Basics == There are three basic path formats: * portable (with a forward slash) * local (slash on Unix, backslash on Windows) * (what is the third? ??SimonHeimberg) OS-specific observations: * Despite usually using backslash, Windows internally will always accept slash instead of backslash <> * Backslashes are valid non-separator characters on Unix, which we should be able to store (though the repo may not be usable on Windows) * On Windows, ui.slash will cause some commands to output slashes Basic rules: * paths stored in changelog and manifest should always be in portable format * paths read from user (command line, config files) may be in either portable or local format * URLs should always use portable format APIs: * convert from native to portable with util.pconvert() * convert from portable to native with util.localpath() * util.normpath() converts to portable * repo.pathto() and dirstate.pathto() converts to local (honors ui.slash) * util.pathto() converts to local (ignores ui.slash) == Audit of current usage == As of Mercurial 2.4, we have the following behavior: ||command ||output || ui.slash || comments || ||hg add/copy/forget/rename/remove/revert ||local || no || || ||hg diff/export ||portable || || || ||hg locate ||portable || || unusual for working directory command || ||hg manifest ||portable || || || ||hg log ||portable || || || ||hg resolve ||portable || ||unusual for working directory command || ||hg status ||local || yes ||even if not checking working directory || ||hg clone/push/pull/in/out ||local ||no ||shows normalized source || ||hg rebase/strip ||local ||no ||reports path of backup bundle || Inferred rules: * commands for inspecting history should use portable format * commands for working directory should use local format * commands that default to the working directory (ie status) should use local format * diffs should use portable format... for portability == Tests == As of [[http://www.selenic.com/hg/rev/9910f60a37ee|2.4]], the Mercurial test suite uses the '(glob)' filter to hide Windows-specific path changes (and ui.slash=on). This has several downsides: * Unix developers usually fail to mark these paths when writing tests * doesn't detect accidental regressions (what kind of regressions? ??SimonHeimberg) * tedious to maintain Some possible improvements: * a new filter '(path)' that normalizes local paths but complains about non-local paths * an automatic filter that accepts "\" for "/" on Windows (when we are not interested where \ is used, [[http://www.selenic.com/pipermail/mercurial-devel/2012-October/045189.html|proposed here]]) * more complete check-code rules to warn Unix devs about non-portable constructs ([[http://www.selenic.com/pipermail/mercurial-devel/2013-February/049424.html|proposed here]]) Questions related to Tests: * Should we really test with ui.slash=on? Are we not more interested in the normal behavior? (To see where we use local and where portable.) == Questions == * Considering how inconsistent Mercurial uses portable vs local slashes: * Do Windows users actually rely on Mercurial emitting backslash? * One feedback in the forum was that "/" is irritating, but ok, as long as copy and paste works. (Also copying to other programs.) * Is there a use case for the setting ui.slash? * A user in the forum asked how to print / for \ and was pleased to hear of ui.slash. But he did not tell what for. * How much time does Mercurial spend normalizing paths and converting slashes over and over? == Notes == * Windows accepts / as path sep except * the two backslashes at start of a server path ({{{//computer/path/to}}}) in explorer (but mercurial does accept it). An alternative writing form the explorer accepts is {{{file://computer/path/to}}} ---- ## list categories here