Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-29956

Wipe out repository & force clone ignore's Windows directory junctions

      During building, I have a custom build script that does the following:
      1. Downloads dependency code to the machine in a specific location.
      2. In the Jenkins workspace directory, it creates a pointer that specific location:
      – On Windows, it uses directory junctions (mklink /J <dest> <src>). I use directory junctions because Symlinks are disabled by default in my environment.
      – On Linux, it uses symlinks (ln -s <src> <dest>)
      3. Builds the code

      When this project is built again, I have the "Wipe out repository & force clone" option set to make sure that we get a clean clone for GIT. This code calls down to hudson.FilePath.deleteContents(), which calls deleteContentsRecursive(), which calls deleteRecursive(). In here, we have
      if (!isSymlink(dir))
      deleteContensRecursive(dir)
      try

      { deleteFile(deleting(dir)) }

      ....

      In this call to isSymlink(), it is not determining that my Windows directory junction is really just a symlink. So, it is proceeding down the junction and deleting the machine cache contents, which is not wanted. On Linux, it properly detects the symlink, and only deletes the symlink.

      It looks like the change that causes this was introduced in ed748d4 – Try to use NIO.2 for Java 7. It was subsequently revised to put this code into it's own function (b6f924d) Unfortunately, the Java 7 isSymbolicLink function does not count a Windows directory junction as a symlink either. You have to go to BasicFileAttributes and call isOther to along with isSymbolicLink to determine if the path in question is a Windows reparse point (Windows directory junctions are reparse poitns).

      This change of using Java 7 (if available) was done right before a function designed to check on Windows for either a Windows symbolic link (CreateSymbolicLink) or Directory junction (parse point). That function is Kernel32Utils.isJunctionOrSymlink(file). If this call is moved before the call to the isSymlinkJava7, then it will properly detect the directory junction and not recursively remove it's contents. It will just remove the junction.

      I have created a Pull-Request that implements this change (https://github.com/jenkinsci/jenkins/pull/1787).

          [JENKINS-29956] Wipe out repository & force clone ignore's Windows directory junctions

          Linus Geson added a comment -

          I encountered this issue as well. When using the built-in deleteDir step provided by the workflow plugin (1.11) it follows a directory junction in Windows and deletes the content of it. The deleteDir code uses hudson.FilePath.deleteRecursive().

          Linus Geson added a comment - I encountered this issue as well. When using the built-in deleteDir step provided by the workflow plugin (1.11) it follows a directory junction in Windows and deletes the content of it. The deleteDir code uses hudson.FilePath.deleteRecursive().

          Code changed in jenkins
          User: dbroady1
          Path:
          core/src/main/java/hudson/Util.java
          core/src/test/java/hudson/RemoveWindowsDirectoryJunctionTest.java
          http://jenkins-ci.org/commit/jenkins/f4edf91782720d2e1246ddb48554511912af1491
          Log:
          JENKINS-29956 Test Windows junctions before Java 7 symlink (#1787)

          • Test Windows junctions before Java 7 symlink

          Apparently Java 7 (and later) do not count Windows junctions as
          symlinks. When you drill down into the BasicFileAttributes structure,
          reparse points are only counted under isOther. So, since we already
          have code that properly detects Windows Junctions, let's use that first
          and then fallback to the Java 7 code.

          • Add comment for change & link bug.
          • Add test case
          • Switch to Functions.isWindows().
          • Use non-deprecated APIs for tmp file/dir mgmt
          • Add better debugging.
          • Allow spaces in junction name & dir name.

          To do that, it was easier to use ProcessBuilder vs building up the correct
          string in code to send to cmd.exe.

          Also, I'll note that according to http://ss64.com/nt/syntax-internal.html,
          mklink is in internal cmd.exe command. So, it must be invoked through
          "cmd.exe /c" for it to work.

          • Remove comment mentioning bug number.
          • Remove debugging output, per Baptiste's request
          • Add newline at end of file.
          • Make sure that the junction was removed.
          • Use assertEquals to show retcode of Process.waitFor.
          • Fix compilation errors by importing functions

          SCM/JIRA link daemon added a comment - Code changed in jenkins User: dbroady1 Path: core/src/main/java/hudson/Util.java core/src/test/java/hudson/RemoveWindowsDirectoryJunctionTest.java http://jenkins-ci.org/commit/jenkins/f4edf91782720d2e1246ddb48554511912af1491 Log: JENKINS-29956 Test Windows junctions before Java 7 symlink (#1787) Test Windows junctions before Java 7 symlink Apparently Java 7 (and later) do not count Windows junctions as symlinks. When you drill down into the BasicFileAttributes structure, reparse points are only counted under isOther. So, since we already have code that properly detects Windows Junctions, let's use that first and then fallback to the Java 7 code. Add comment for change & link bug. Add test case Switch to Functions.isWindows(). Use non-deprecated APIs for tmp file/dir mgmt Add better debugging. Allow spaces in junction name & dir name. To do that, it was easier to use ProcessBuilder vs building up the correct string in code to send to cmd.exe. Also, I'll note that according to http://ss64.com/nt/syntax-internal.html , mklink is in internal cmd.exe command. So, it must be invoked through "cmd.exe /c" for it to work. Remove comment mentioning bug number. Remove debugging output, per Baptiste's request Add newline at end of file. Make sure that the junction was removed. Use assertEquals to show retcode of Process.waitFor. Fix compilation errors by importing functions

          Oleg Nenashev added a comment -

          The fix has been merged towards jenkins-2.20

          Oleg Nenashev added a comment - The fix has been merged towards jenkins-2.20

          oleg_nenashev Could this be backported to an LTS release?

          Michael Fowler added a comment - oleg_nenashev Could this be backported to an LTS release?

          Oleg Nenashev added a comment -

          mdkf It's planned to 2.19.1, which is expected to be released within 3 weeks.
          Backporting to 2,7,x is not in the plan according to the current release model

          Oleg Nenashev added a comment - mdkf It's planned to 2.19.1, which is expected to be released within 3 weeks. Backporting to 2,7,x is not in the plan according to the current release model

            Unassigned Unassigned
            dbroady1 Darin Broady
            Votes:
            2 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: