Skip to content
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

CopyFiles doesn't respect source directory structure #899

Closed
thomaslevesque opened this issue May 19, 2016 · 12 comments · Fixed by #1145
Closed

CopyFiles doesn't respect source directory structure #899

thomaslevesque opened this issue May 19, 2016 · 12 comments · Fixed by #1145
Labels
Milestone

Comments

@thomaslevesque
Copy link
Contributor

What You Are Seeing?

If I have a directory structure like this:

root
-- subdir1
---- bar.dll
-- subdir2
---- baz.dll
-- foo.exe

When I execute this:

CopyFiles("root/**/*", outputDir);

The files are copied to a flat directory structure, instead of preserving the original structure:

outputDir
-- foo.exe
-- bar.dll
-- baz.dll

What is Expected?

The same structure as in the source folder

outputDir
-- subdir1
---- bar.dll
-- subdir2
---- baz.dll
-- foo.exe

What version of Cake are you using?

0.11

Are you running on a 32 or 64 bit system?

64 bit

What environment are you running on? Windows? Linux? Mac?

Windows 8.1

Are you running on a CI Server? If so, which one?

Not at this point, just testing locally (but eventually it will run on Jenkins)

How Did You Get This To Happen? (Steps to Reproduce)

As described above

Output Log

...
========================================
PublishArtifacts
========================================
Executing task: PublishArtifacts
Copying file foo.exe to D:/path/to/outputDir/foo.exe
Copying file bar.dll to D:/path/to/outputDir/foo.exe
Copying file baz.dll to D:/path/to/outputDir/foo.exe
Finished executing task: PublishArtifacts
...

I realize this may be the intended behavior, but I don't think it makes much sense... especially since there doesn't seem to be an easy way to manually list and copy the files.

@devlead
Copy link
Member

devlead commented May 19, 2016

@thomaslevesque Hi, this is by design, but we have discussed it before so think we should add an overload with something like bool preserveFolderStructure or similar.

@thomaslevesque
Copy link
Contributor Author

think we should add an overload with something like bool preserveFolderStructure or similar.

That would be awesome!

In the meantime, I'll find a workaround

@devlead
Copy link
Member

devlead commented May 19, 2016

Superb, if it's a good workaround you should submit a 😉
You could probably use same globber with GetFiles and the upcoming EnsureDirectoryExists validating relatively that each files parent exist.

@thomaslevesque
Copy link
Contributor Author

Here's my (ugly) workaround:

    void CopyFilesPreservingStructure(string pattern, DirectoryPath destinationDir)
    {
        int firstWildcardIndex = pattern.IndexOf('*');
        var patternRootRelativePath = firstWildcardIndex < 0
          ? System.IO.Path.GetDirectoryName(pattern)
          : pattern.Substring(0, firstWildcardIndex);

        var patternRoot = MakeAbsolute(Directory(patternRootRelativePath));

        var files = GetFiles(pattern);
        foreach (var file in files)
        {
          var relativeFile = patternRoot.GetRelativePath(file);
          var destinationFile = destinationDir.CombineWithFilePath(relativeFile);
          var parent = destinationFile.GetDirectory();
          if (!DirectoryExists(parent))
            CreateDirectory(parent);
          CopyFile(file, destinationFile);
        }
    }

@danielfrancora
Copy link

Hello thomaslevesque.
I'm working with the same issue as you. How did you invoke this function you created? I'm trying to use it but with no luck.
Thx for the help.

@thomaslevesque
Copy link
Contributor Author

How did you invoke this function you created?

Something like this:

CopyFilesPreservingStructure($"src/MyProject/bin/{configuration}/**/*.exe", "artifacts");

@robgha01
Copy link

I tested this workaround method with the following but it wont work same output as CopyFiles(pattern

var root = "../";
var projectRoot =  MakeAbsolute(Directory(root));
var projectName =  Argument("projectName", ((DirectoryPath)(MakeAbsolute(Directory(root)).FullPath)).GetDirectoryName());
var buildDir = projectRoot + Directory($"/{projectName}");
var files = new [] {
        $"{buildDir}/bin/*.dll",
        $"{buildDir}/DataServices/*.svc",
        $"{buildDir}/scripts/**",
        $"{buildDir}/*.config",
        $"{buildDir}/*.aspx",
        $"{buildDir}/*.ico",
        $"{buildDir}/*.html"
    };

    foreach(var pattern in files) {
        CopyFilesPreservingStructure(pattern, targetOutput);
    }

@thomaslevesque
Copy link
Contributor Author

@robgha01, it's just a quick and dirty workaround, I haven't tested it thoroughly... it works well enough for my needs, but I can't guarantee anything beyond that.

@RyannosaurusRex
Copy link

I could totally be missing something here, but is what you want actually CopyDirectory instead of Copy files? I ran into a similar thing where I tried to use CopyFiles to copy a directory and ended up using CopyDirectory, which worked for me.

@thomaslevesque
Copy link
Contributor Author

I could totally be missing something here, but is what you want actually CopyDirectory instead of Copy files? I ran into a similar thing where I tried to use CopyFiles to copy a directory and ended up using CopyDirectory, which worked for me.

From what I can see in the documentation, it's absolutely possible that I should be using CopyDirectory... I'll give it a try, thanks.

@thomaslevesque
Copy link
Contributor Author

Actually... maybe not. I use globbing to specify which files to copy, and CopyDirectory just copies all files.

@martinscholz83
Copy link
Contributor

martinscholz83 commented Aug 3, 2016

Hi there, i want to ask if this issue is still present. I have created some overloads where you can select to keep the folder structure for CopyFiles.
For example

Task("A")
    .Does(() => 
{
    CopyFiles("root/**/*.js", "target", true);
});

RunTarget("A")

Should i create a pull request to show?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants