Move OneDrive path helper func to path package (#1880)

## Description

Later code in details package will need access to this function so it can update item details. However, importing the onedrive package in the details package leads to an import cycle. Moving it to the path package breaks the cycle while still allowing the code to be accessed.

## Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No 

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [x] 🐹 Trivial/Minor

## Issue(s)

* #1800 

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-12-21 15:32:47 -08:00 committed by GitHub
parent 5b6b60de60
commit df086bd6f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 48 deletions

View File

@ -182,7 +182,7 @@ func (oc *Collection) populateItems(ctx context.Context) {
// Retrieve the OneDrive folder path to set later in // Retrieve the OneDrive folder path to set later in
// `details.OneDriveInfo` // `details.OneDriveInfo`
parentPathString, err := getDriveFolderPath(oc.folderPath) parentPathString, err := path.GetDriveFolderPath(oc.folderPath)
if err != nil { if err != nil {
oc.reportAsCompleted(ctx, 0, 0, err) oc.reportAsCompleted(ctx, 0, 0, err)
return return

View File

@ -18,6 +18,7 @@ import (
"github.com/alcionai/corso/src/internal/data" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/path"
) )
type CollectionUnitTestSuite struct { type CollectionUnitTestSuite struct {
@ -102,7 +103,7 @@ func (suite *CollectionUnitTestSuite) TestCollection() {
folderPath, err := GetCanonicalPath("drive/driveID1/root:/dir1/dir2/dir3", "tenant", "owner", test.source) folderPath, err := GetCanonicalPath("drive/driveID1/root:/dir1/dir2/dir3", "tenant", "owner", test.source)
require.NoError(t, err) require.NoError(t, err)
driveFolderPath, err := getDriveFolderPath(folderPath) driveFolderPath, err := path.GetDriveFolderPath(folderPath)
require.NoError(t, err) require.NoError(t, err)
coll := NewCollection( coll := NewCollection(

View File

@ -189,19 +189,9 @@ func GetCanonicalPath(p, tenant, resourceOwner string, source driveSource) (path
return result, nil return result, nil
} }
// Returns the path to the folder within the drive (i.e. under `root:`)
func getDriveFolderPath(p path.Path) (string, error) {
drivePath, err := toOneDrivePath(p)
if err != nil {
return "", err
}
return path.Builder{}.Append(drivePath.folders...).String(), nil
}
func includePath(ctx context.Context, m folderMatcher, folderPath path.Path) bool { func includePath(ctx context.Context, m folderMatcher, folderPath path.Path) bool {
// Check if the folder is allowed by the scope. // Check if the folder is allowed by the scope.
folderPathString, err := getDriveFolderPath(folderPath) folderPathString, err := path.GetDriveFolderPath(folderPath)
if err != nil { if err != nil {
logger.Ctx(ctx).Error(err) logger.Ctx(ctx).Error(err)
return true return true

View File

@ -25,28 +25,6 @@ const (
copyBufferSize = 5 * 1024 * 1024 copyBufferSize = 5 * 1024 * 1024
) )
// drivePath is used to represent path components
// of an item within the drive i.e.
// Given `drives/b!X_8Z2zuXpkKkXZsr7gThk9oJpuj0yXVGnK5_VjRRPK-q725SX_8ZQJgFDK8PlFxA/root:/Folder1/Folder2/file`
//
// driveID is `b!X_8Z2zuXpkKkXZsr7gThk9oJpuj0yXVGnK5_VjRRPK-q725SX_8ZQJgFDK8PlFxA` and
// folders[] is []{"Folder1", "Folder2"}
type drivePath struct {
driveID string
folders []string
}
func toOneDrivePath(p path.Path) (*drivePath, error) {
folders := p.Folders()
// Must be at least `drives/<driveID>/root:`
if len(folders) < 3 {
return nil, errors.Errorf("folder path doesn't match expected format for OneDrive items: %s", p.Folder())
}
return &drivePath{driveID: folders[1], folders: folders[3:]}, nil
}
// RestoreCollections will restore the specified data collections into OneDrive // RestoreCollections will restore the specified data collections into OneDrive
func RestoreCollections( func RestoreCollections(
ctx context.Context, ctx context.Context,
@ -107,7 +85,7 @@ func RestoreCollection(
directory = dc.FullPath() directory = dc.FullPath()
) )
drivePath, err := toOneDrivePath(directory) drivePath, err := path.ToOneDrivePath(directory)
if err != nil { if err != nil {
errUpdater(directory.String(), err) errUpdater(directory.String(), err)
return metrics, false return metrics, false
@ -118,13 +96,13 @@ func RestoreCollection(
// i.e. Restore into `<drive>/root:/<restoreContainerName>/<original folder path>` // i.e. Restore into `<drive>/root:/<restoreContainerName>/<original folder path>`
restoreFolderElements := []string{restoreContainerName} restoreFolderElements := []string{restoreContainerName}
restoreFolderElements = append(restoreFolderElements, drivePath.folders...) restoreFolderElements = append(restoreFolderElements, drivePath.Folders...)
trace.Log(ctx, "gc:oneDrive:restoreCollection", directory.String()) trace.Log(ctx, "gc:oneDrive:restoreCollection", directory.String())
logger.Ctx(ctx).Debugf("Restore target for %s is %v", dc.FullPath(), restoreFolderElements) logger.Ctx(ctx).Debugf("Restore target for %s is %v", dc.FullPath(), restoreFolderElements)
// Create restore folders and get the folder ID of the folder the data stream will be restored in // Create restore folders and get the folder ID of the folder the data stream will be restored in
restoreFolderID, err := createRestoreFolders(ctx, service, drivePath.driveID, restoreFolderElements) restoreFolderID, err := createRestoreFolders(ctx, service, drivePath.DriveID, restoreFolderElements)
if err != nil { if err != nil {
errUpdater(directory.String(), errors.Wrapf(err, "failed to create folders %v", restoreFolderElements)) errUpdater(directory.String(), errors.Wrapf(err, "failed to create folders %v", restoreFolderElements))
return metrics, false return metrics, false
@ -150,7 +128,7 @@ func RestoreCollection(
itemInfo, err := restoreItem(ctx, itemInfo, err := restoreItem(ctx,
service, service,
itemData, itemData,
drivePath.driveID, drivePath.DriveID,
restoreFolderID, restoreFolderID,
copyBuffer, copyBuffer,
source) source)

40
src/pkg/path/onedrive.go Normal file
View File

@ -0,0 +1,40 @@
package path
import (
"github.com/pkg/errors"
)
// drivePath is used to represent path components
// of an item within the drive i.e.
// Given `drives/b!X_8Z2zuXpkKkXZsr7gThk9oJpuj0yXVGnK5_VjRRPK-q725SX_8ZQJgFDK8PlFxA/root:/Folder1/Folder2/file`
//
// driveID is `b!X_8Z2zuXpkKkXZsr7gThk9oJpuj0yXVGnK5_VjRRPK-q725SX_8ZQJgFDK8PlFxA` and
// folders[] is []{"Folder1", "Folder2"}
type DrivePath struct {
DriveID string
Folders []string
}
func ToOneDrivePath(p Path) (*DrivePath, error) {
folders := p.Folders()
// Must be at least `drives/<driveID>/root:`
if len(folders) < 3 {
return nil, errors.Errorf(
"folder path doesn't match expected format for OneDrive items: %s",
p.Folder(),
)
}
return &DrivePath{DriveID: folders[1], Folders: folders[3:]}, nil
}
// Returns the path to the folder within the drive (i.e. under `root:`)
func GetDriveFolderPath(p Path) (string, error) {
drivePath, err := ToOneDrivePath(p)
if err != nil {
return "", err
}
return Builder{}.Append(drivePath.Folders...).String(), nil
}

View File

@ -1,4 +1,4 @@
package onedrive package path_test
import ( import (
"testing" "testing"
@ -10,19 +10,19 @@ import (
"github.com/alcionai/corso/src/pkg/path" "github.com/alcionai/corso/src/pkg/path"
) )
type OneDriveRestoreSuite struct { type OneDrivePathSuite struct {
suite.Suite suite.Suite
} }
func TestOneDriveRestoreSuite(t *testing.T) { func TestOneDrivePathSuite(t *testing.T) {
suite.Run(t, new(OneDriveRestoreSuite)) suite.Run(t, new(OneDrivePathSuite))
} }
func (suite *OneDriveRestoreSuite) Test_toOneDrivePath() { func (suite *OneDrivePathSuite) Test_ToOneDrivePath() {
tests := []struct { tests := []struct {
name string name string
pathElements []string pathElements []string
expected *drivePath expected *path.DrivePath
errCheck assert.ErrorAssertionFunc errCheck assert.ErrorAssertionFunc
}{ }{
{ {
@ -33,13 +33,13 @@ func (suite *OneDriveRestoreSuite) Test_toOneDrivePath() {
{ {
name: "Root path", name: "Root path",
pathElements: []string{"drive", "driveID", "root:"}, pathElements: []string{"drive", "driveID", "root:"},
expected: &drivePath{driveID: "driveID", folders: []string{}}, expected: &path.DrivePath{DriveID: "driveID", Folders: []string{}},
errCheck: assert.NoError, errCheck: assert.NoError,
}, },
{ {
name: "Deeper path", name: "Deeper path",
pathElements: []string{"drive", "driveID", "root:", "folder1", "folder2"}, pathElements: []string{"drive", "driveID", "root:", "folder1", "folder2"},
expected: &drivePath{driveID: "driveID", folders: []string{"folder1", "folder2"}}, expected: &path.DrivePath{DriveID: "driveID", Folders: []string{"folder1", "folder2"}},
errCheck: assert.NoError, errCheck: assert.NoError,
}, },
} }
@ -48,7 +48,7 @@ func (suite *OneDriveRestoreSuite) Test_toOneDrivePath() {
p, err := path.Builder{}.Append(tt.pathElements...).ToDataLayerOneDrivePath("tenant", "user", false) p, err := path.Builder{}.Append(tt.pathElements...).ToDataLayerOneDrivePath("tenant", "user", false)
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
got, err := toOneDrivePath(p) got, err := path.ToOneDrivePath(p)
tt.errCheck(t, err) tt.errCheck(t, err)
if err != nil { if err != nil {
return return