internal/copydir: Factor out our recursive directory copy for reuse

We've previously been copying this function around so it could remain
unexported while being used in various packages. However, it's a
non-trivial function with lots of specific assumptions built into it, so
here we'll put it somewhere that other packages can depend on it _and_
document the assumptions it seems to be making for future reference.

As a bonus, this now uses os.SameFile to detect when two paths point to
the same physical file, instead of the slightly buggy local implementation
we had before which only worked on Unix systems and did not correctly
handle when the paths were on different physical devices.

The copy of the function I extracted here is the one from internal/initwd,
so this commit also includes the removal of that unexported version and
updating the callers in that package to use at at this new location.
This commit is contained in:
Martin Atkins
2020-03-11 17:17:30 -07:00
parent d13001830b
commit 072c6d9aed
8 changed files with 48 additions and 73 deletions

View File

@@ -2,7 +2,6 @@ package initwd
import (
"fmt"
"github.com/hashicorp/terraform/internal/earlyconfig"
"io/ioutil"
"log"
"os"
@@ -10,8 +9,11 @@ import (
"sort"
"strings"
"github.com/hashicorp/terraform/internal/earlyconfig"
version "github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-config-inspect/tfconfig"
"github.com/hashicorp/terraform/internal/copydir"
"github.com/hashicorp/terraform/internal/modsdir"
"github.com/hashicorp/terraform/registry"
"github.com/hashicorp/terraform/tfdiags"
@@ -172,7 +174,7 @@ func DirFromModule(rootDir, modulesDir, sourceAddr string, reg *registry.Client,
// We've found the module the user requested, which we must
// now copy into rootDir so it can be used directly.
log.Printf("[TRACE] copying new root module from %s to %s", record.Dir, rootDir)
err := copyDir(rootDir, record.Dir)
err := copydir.CopyDir(rootDir, record.Dir)
if err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
@@ -292,7 +294,7 @@ func DirFromModule(rootDir, modulesDir, sourceAddr string, reg *registry.Client,
// We copy rather than "rename" here because renaming between directories
// can be tricky in edge-cases like network filesystems, etc.
log.Printf("[TRACE] copying new module %s from %s to %s", newKey, record.Dir, instPath)
err := copyDir(instPath, tempPath)
err := copydir.CopyDir(instPath, tempPath)
if err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,