corso/src/pkg/export/consume.go
Abin Simon c654dfba1b
Export data from SharePoint (#3824)
This borrows a lot of the core logic from OneDrive as the internal structure is mostly the same.

<!-- PR description-->
Prev: https://github.com/alcionai/corso/pull/3822

---

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

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

#### Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

#### Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* fixes https://github.com/alcionai/corso/issues/3823

#### Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
2023-07-28 08:40:35 +00:00

80 lines
1.6 KiB
Go

package export
import (
"context"
"io"
"os"
"path/filepath"
"github.com/alcionai/clues"
"github.com/alcionai/corso/src/internal/observe"
"github.com/alcionai/corso/src/pkg/fault"
)
func ConsumeExportCollections(
ctx context.Context,
exportLocation string,
expColl []Collection,
errs *fault.Bus,
) error {
el := errs.Local()
for _, col := range expColl {
if el.Failure() != nil {
break
}
folder := filepath.Join(exportLocation, col.BasePath())
ictx := clues.Add(ctx, "dir_name", folder)
for item := range col.Items(ctx) {
if item.Error != nil {
el.AddRecoverable(ictx, clues.Wrap(item.Error, "getting item").WithClues(ctx))
}
if err := writeItem(ictx, item, folder); err != nil {
el.AddRecoverable(
ictx,
clues.Wrap(err, "writing item").With("file_name", item.Data.Name).WithClues(ctx))
}
}
}
return el.Failure()
}
// writeItem writes an ExportItem to disk in the specified folder.
func writeItem(ctx context.Context, item Item, folder string) error {
name := item.Data.Name
fpath := filepath.Join(folder, name)
progReader, pclose := observe.ItemSpinner(
ctx,
item.Data.Body,
observe.ItemExportMsg,
clues.Hide(name))
defer item.Data.Body.Close()
defer pclose()
err := os.MkdirAll(folder, os.ModePerm)
if err != nil {
return clues.Wrap(err, "creating directory")
}
// In case the user tries to restore to a non-clean
// directory, we might run into collisions an fail.
f, err := os.Create(fpath)
if err != nil {
return clues.Wrap(err, "creating file")
}
_, err = io.Copy(f, progReader)
if err != nil {
return clues.Wrap(err, "writing data")
}
return nil
}