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

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

    XMLWordPrintable

    Details

    • Similar Issues:

      Description

      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).

        Attachments

          Issue Links

            Activity

            Hide
            hms_lig 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().

            Show
            hms_lig 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().
            Hide
            scm_issue_link 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
            Show
            scm_issue_link 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
            Hide
            oleg_nenashev Oleg Nenashev added a comment -

            The fix has been merged towards jenkins-2.20

            Show
            oleg_nenashev Oleg Nenashev added a comment - The fix has been merged towards jenkins-2.20
            Hide
            mdkf Michael Fowler added a comment -

            Oleg Nenashev Could this be backported to an LTS release?

            Show
            mdkf Michael Fowler added a comment - Oleg Nenashev Could this be backported to an LTS release?
            Hide
            oleg_nenashev Oleg Nenashev added a comment -

            Michael Fowler 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

            Show
            oleg_nenashev Oleg Nenashev added a comment - Michael Fowler 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

              People

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

                Dates

                • Created:
                  Updated:
                  Resolved: