diff --git a/src/internal/connector/onedrive/collection.go b/src/internal/connector/onedrive/collection.go index e579654e1..77caf18a6 100644 --- a/src/internal/connector/onedrive/collection.go +++ b/src/internal/connector/onedrive/collection.go @@ -45,7 +45,7 @@ type itemReaderFunc func( ctx context.Context, service graph.Service, driveID, itemID string, -) (name string, itemData io.ReadCloser, err error) +) (itemInfo *details.OneDriveInfo, itemData io.ReadCloser, err error) // NewCollection creates a Collection func NewCollection( @@ -113,7 +113,7 @@ func (oc *Collection) populateItems(ctx context.Context) { for _, itemID := range oc.driveItemIDs { // Read the item - itemName, itemData, err := oc.itemReader(ctx, oc.service, oc.driveID, itemID) + itemInfo, itemData, err := oc.itemReader(ctx, oc.service, oc.driveID, itemID) if err != nil { errs = support.WrapAndAppendf(itemID, err, errs) @@ -125,14 +125,13 @@ func (oc *Collection) populateItems(ctx context.Context) { } // Item read successfully, add to collection itemsRead++ + + itemInfo.ParentPath = oc.folderPath.String() + oc.data <- &Item{ - id: itemName, + id: itemInfo.ItemName, data: itemData, - info: &details.OneDriveInfo{ - ItemType: details.OneDriveItem, - ItemName: itemName, - ParentPath: oc.folderPath.String(), - }, + info: itemInfo, } } diff --git a/src/internal/connector/onedrive/collection_test.go b/src/internal/connector/onedrive/collection_test.go index 203af0c6a..fa84563c2 100644 --- a/src/internal/connector/onedrive/collection_test.go +++ b/src/internal/connector/onedrive/collection_test.go @@ -16,6 +16,7 @@ import ( "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/support" "github.com/alcionai/corso/src/internal/data" + "github.com/alcionai/corso/src/pkg/backup/details" ) type OneDriveCollectionSuite struct { @@ -73,8 +74,8 @@ func (suite *OneDriveCollectionSuite) TestOneDriveCollection() { // Set a item reader, add an item and validate we get the item back coll.Add(testItemID) - coll.itemReader = func(context.Context, graph.Service, string, string) (string, io.ReadCloser, error) { - return testItemName, io.NopCloser(bytes.NewReader(testItemData)), nil + coll.itemReader = func(context.Context, graph.Service, string, string) (*details.OneDriveInfo, io.ReadCloser, error) { + return &details.OneDriveInfo{ItemName: testItemName}, io.NopCloser(bytes.NewReader(testItemData)), nil } // Read items from the collection @@ -122,8 +123,8 @@ func (suite *OneDriveCollectionSuite) TestOneDriveCollectionReadError() { readError := errors.New("Test error") - coll.itemReader = func(context.Context, graph.Service, string, string) (name string, data io.ReadCloser, err error) { - return "", nil, readError + coll.itemReader = func(context.Context, graph.Service, string, string) (*details.OneDriveInfo, io.ReadCloser, error) { + return nil, nil, readError } coll.Items() diff --git a/src/internal/connector/onedrive/item.go b/src/internal/connector/onedrive/item.go index f76e989f2..6db6ec35a 100644 --- a/src/internal/connector/onedrive/item.go +++ b/src/internal/connector/onedrive/item.go @@ -14,6 +14,7 @@ import ( "github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/support" + "github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/logger" ) @@ -30,19 +31,19 @@ func driveItemReader( ctx context.Context, service graph.Service, driveID, itemID string, -) (string, io.ReadCloser, error) { +) (*details.OneDriveInfo, io.ReadCloser, error) { logger.Ctx(ctx).Debugf("Reading Item %s at %s", itemID, time.Now()) item, err := service.Client().DrivesById(driveID).ItemsById(itemID).Get(ctx, nil) if err != nil { - return "", nil, errors.Wrapf(err, "failed to get item %s", itemID) + return nil, nil, errors.Wrapf(err, "failed to get item %s", itemID) } // Get the download URL - https://docs.microsoft.com/en-us/graph/api/driveitem-get-content // These URLs are pre-authenticated and can be used to download the data using the standard // http client if _, found := item.GetAdditionalData()[downloadURLKey]; !found { - return "", nil, errors.Errorf("file does not have a download URL. ID: %s, %#v", + return nil, nil, errors.Errorf("file does not have a download URL. ID: %s, %#v", itemID, item.GetAdditionalData()) } @@ -52,10 +53,16 @@ func driveItemReader( // middleware/options configured resp, err := http.Get(*downloadURL) if err != nil { - return "", nil, errors.Wrapf(err, "failed to download file from %s", *downloadURL) + return nil, nil, errors.Wrapf(err, "failed to download file from %s", *downloadURL) } - return *item.GetName(), resp.Body, nil + return &details.OneDriveInfo{ + ItemType: details.OneDriveItem, + ItemName: *item.GetName(), + Created: *item.GetCreatedDateTime(), + LastModified: *item.GetLastModifiedDateTime(), + Size: *item.GetSize(), + }, resp.Body, nil } // driveItemWriter is used to initialize and return an io.Writer to upload data for the specified item diff --git a/src/internal/connector/onedrive/item_test.go b/src/internal/connector/onedrive/item_test.go index f5f02f172..3e7f23e9e 100644 --- a/src/internal/connector/onedrive/item_test.go +++ b/src/internal/connector/onedrive/item_test.go @@ -102,14 +102,16 @@ func (suite *ItemIntegrationSuite) TestItemReader() { ) // Read data for the file - name, itemData, err := driveItemReader(ctx, suite, driveID, driveItemID) + itemInfo, itemData, err := driveItemReader(ctx, suite, driveID, driveItemID) require.NoError(suite.T(), err) - require.NotEmpty(suite.T(), name) + require.NotNil(suite.T(), itemInfo) + require.NotEmpty(suite.T(), itemInfo.ItemName) size, err := io.Copy(io.Discard, itemData) require.NoError(suite.T(), err) require.NotZero(suite.T(), size) - suite.T().Logf("Read %d bytes from file %s.", size, name) + require.Equal(suite.T(), size, itemInfo.Size) + suite.T().Logf("Read %d bytes from file %s.", size, itemInfo.ItemName) } // TestItemWriter is an integration test for uploading data to OneDrive diff --git a/src/pkg/backup/details/details.go b/src/pkg/backup/details/details.go index 91353b7e8..4942e2be7 100644 --- a/src/pkg/backup/details/details.go +++ b/src/pkg/backup/details/details.go @@ -361,19 +361,25 @@ func (i SharepointInfo) Values() []string { // OneDriveInfo describes a oneDrive item type OneDriveInfo struct { - ItemType ItemType `json:"itemType,omitempty"` - ParentPath string `json:"parentPath"` - ItemName string `json:"itemName"` + ItemType ItemType `json:"itemType,omitempty"` + ParentPath string `json:"parentPath"` + ItemName string `json:"itemName"` + Size int64 `json:"size,omitempty"` + Created time.Time `json:"created,omitempty"` + LastModified time.Time `json:"lastModified,omitempty"` } // Headers returns the human-readable names of properties in a OneDriveInfo // for printing out to a terminal in a columnar display. func (i OneDriveInfo) Headers() []string { - return []string{"ItemName", "ParentPath"} + return []string{"ItemName", "ParentPath", "Size", "Created", "LastModified"} } // Values returns the values matching the Headers list for printing // out to a terminal in a columnar display. func (i OneDriveInfo) Values() []string { - return []string{i.ItemName, i.ParentPath} + return []string{ + i.ItemName, i.ParentPath, strconv.FormatInt(i.Size, 10), + common.FormatTabularDisplayTime(i.Created), common.FormatTabularDisplayTime(i.LastModified), + } } diff --git a/src/pkg/backup/details/details_test.go b/src/pkg/backup/details/details_test.go index 6cd047908..fbfe7a94a 100644 --- a/src/pkg/backup/details/details_test.go +++ b/src/pkg/backup/details/details_test.go @@ -112,13 +112,16 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() { ShortRef: "deadbeef", ItemInfo: details.ItemInfo{ OneDrive: &details.OneDriveInfo{ - ItemName: "itemName", - ParentPath: "parentPath", + ItemName: "itemName", + ParentPath: "parentPath", + Size: 1000, + Created: now, + LastModified: now, }, }, }, - expectHs: []string{"Reference", "ItemName", "ParentPath"}, - expectVs: []string{"deadbeef", "itemName", "parentPath"}, + expectHs: []string{"Reference", "ItemName", "ParentPath", "Size", "Created", "LastModified"}, + expectVs: []string{"deadbeef", "itemName", "parentPath", "1000", nowStr, nowStr}, }, }