Here's a rough patch for turning the absolute symlinks into relative
ones. It works on my machine and resolves the issue above.
Would you be willing to take a look?
Are there any larger issues that I haven't considered?
If not, would you be willing to help me polish it into something that
could be accepted?
> diff -r c845bfd0accb config/nsinstall.c
> --- a/config/nsinstall.c Mon Oct 24 16:55:47 2016 +0200
> +++ b/config/nsinstall.c Mon Oct 24 13:26:17 2016 -0700
> @@ -263,13 +263,13 @@
> {
> int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists;
> mode_t mode = 0755;
> - char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, buf[BUFSIZ];
> + char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *absolute, buf[BUFSIZ];
> uid_t uid;
> gid_t gid;
> struct stat sb, tosb, fromsb;
>
> program = argv[0];
> - cwd = linkname = linkprefix = owner = group = 0;
> + cwd = linkname = absolute = linkprefix = owner = group = 0;
> onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
>
> while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
> @@ -379,33 +379,33 @@
> if (access(name, R_OK) != 0) {
> fail("cannot access %s", name);
> }
> - if (*name == '/') {
> - /* source is absolute pathname, link to it directly */
> - linkname = 0;
> - } else {
> if (linkprefix) {
> /* -L prefixes names with a $cwd arg. */
> len += lplen + 1;
> linkname = xmalloc((unsigned int)(len + 1));
> sprintf(linkname, "%s/%s", linkprefix, name);
> } else if (dorelsymlink) {
> + if (*name != '/') {
> + absolute = xmalloc((unsigned int)(strlen(cwd) + 1 + len + 1));
> + sprintf(absolute, "%s/%s", cwd, name);
> + name = absolute;
> + }
> +
> /* Symlink the relative path from todir to source name. */
> linkname = xmalloc(PATH_MAX);
>
> - if (*todir == '/') {
> /* todir is absolute: skip over common prefix. */
> - lplen = relatepaths(todir, cwd, linkname);
> - strcpy(linkname + lplen, name);
> - } else {
> - /* todir is named by a relative path: reverse it. */
> - reversepath(todir, name, len, linkname);
> - xchdir(cwd);
> + len = relatepaths(todir, name, linkname);
> + if (len > 0) {
> + linkname[--len] = '\0';
> }
>
> - len = strlen(linkname);
> + if (absolute) {
> + free(absolute);
> + absolute = 0;
> + }
> }
> name = linkname;
> - }
>
> /* Check for a pre-existing symlink with identical content. */
> if (exists && (!S_ISLNK(tosb.st_mode) ||
> diff -r c845bfd0accb python/mozbuild/mozbuild/jar.py
> --- a/python/mozbuild/mozbuild/jar.py Mon Oct 24 16:55:47 2016 +0200
> +++ b/python/mozbuild/mozbuild/jar.py Mon Oct 24 13:26:17 2016 -0700
> @@ -545,6 +545,7 @@
> if e.errno != errno.ENOENT:
> raise
> if sys.platform != 'win32':
> + src = os.path.relpath(src, os.path.dirname(out))
> os.symlink(src, out)
> else:
> # On Win32, use ctypes to create a hardlink
> diff -r c845bfd0accb python/mozbuild/mozpack/files.py
> --- a/python/mozbuild/mozpack/files.py Mon Oct 24 16:55:47 2016 +0200
> +++ b/python/mozbuild/mozpack/files.py Mon Oct 24 13:26:17 2016 -0700
> @@ -323,23 +323,25 @@
> if ose.errno != errno.ENOENT:
> raise
>
> + src = os.path.relpath(self.path, os.path.dirname(dest))
> +
> # If the dest is a symlink pointing to us, we have nothing to do.
> # If it's the wrong symlink, the filesystem must support symlinks,
> # so we replace with a proper symlink.
> if st and stat.S_ISLNK(st.st_mode):
> link = os.readlink(dest)
> - if link == self.path:
> + if link == src:
> return False
>
> os.remove(dest)
> - os.symlink(self.path, dest)
> + os.symlink(src, dest)
> return True
>
> # If the destination doesn't exist, we try to create a symlink. If that
> # fails, we fall back to copy code.
> if not st:
> try:
> - os.symlink(self.path, dest)
> + os.symlink(src, dest)
> return True
> except OSError:
> return File.copy(self, dest, skip_if_older=skip_if_older)
> @@ -362,7 +364,7 @@
>
> temp_dest = os.path.join(os.path.dirname(dest), str(uuid.uuid4()))
> try:
> - os.symlink(self.path, temp_dest)
> + os.symlink(src, temp_dest)
> # TODO Figure out exactly how symlink creation fails and only trap
> # that.
> except EnvironmentError: