Use short ref during backup (#851)

## Description

Short refs allow the user to type less to select an item to restore. This PR
* Adds a short ref field to the BackupDetails entries
* Populates the short ref field during backup

## Type of change

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

## Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* #572

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-09-14 17:09:28 -07:00 committed by GitHub
parent f8a10b4de6
commit 4cf5fcab5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 30 deletions

View File

@ -278,7 +278,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
for i, ent := range deets.Entries {
t.Run(fmt.Sprintf("detail %d", i), func(t *testing.T) {
assert.Contains(t, result, ent.RepoRef)
assert.Contains(t, result, ent.ShortRef)
})
}
})

View File

@ -55,8 +55,8 @@ func manifestToStats(man *snapshot.Manifest) BackupStats {
}
type itemDetails struct {
info details.ItemInfo
repoRef string
info details.ItemInfo
repoPath path.Path
}
type corsoProgress struct {
@ -89,7 +89,7 @@ func (cp *corsoProgress) FinishedFile(relativePath string, err error) {
return
}
cp.deets.Add(d.repoRef, d.info)
cp.deets.Add(d.repoPath.String(), d.repoPath.ShortRef(), d.info)
}
func (cp *corsoProgress) put(k string, v *itemDetails) {
@ -192,7 +192,7 @@ func getStreamItemFunc(
// element. Add to pending set before calling the callback to avoid race
// conditions when the item is completed.
p := itemPath.PopFront().String()
d := &itemDetails{info: ei.Info(), repoRef: itemPath.String()}
d := &itemDetails{info: ei.Info(), repoPath: itemPath}
progress.put(p, d)

View File

@ -144,8 +144,22 @@ func (suite *CorsoProgressUnitSuite) TestFinishedFile() {
err error
}
targetFileName := "testFile"
deets := &itemDetails{details.ItemInfo{}, targetFileName}
targetFilePath, err := path.Builder{}.Append(
"Inbox",
"testFile",
).ToDataLayerExchangePathForCategory(
testTenant,
testUser,
path.EmailCategory,
true,
)
require.NoError(suite.T(), err)
relativePath, err := targetFilePath.Dir()
require.NoError(suite.T(), err)
targetFileName := relativePath.String()
deets := &itemDetails{details.ItemInfo{}, targetFilePath}
table := []struct {
name string

View File

@ -86,10 +86,14 @@ type Details struct {
mu sync.Mutex `json:"-"`
}
func (d *Details) Add(repoRef string, info ItemInfo) {
func (d *Details) Add(repoRef, shortRef string, info ItemInfo) {
d.mu.Lock()
defer d.mu.Unlock()
d.Entries = append(d.Entries, DetailsEntry{RepoRef: repoRef, ItemInfo: info})
d.Entries = append(d.Entries, DetailsEntry{
RepoRef: repoRef,
ShortRef: shortRef,
ItemInfo: info,
})
}
// --------------------------------------------------------------------------------
@ -100,7 +104,8 @@ func (d *Details) Add(repoRef string, info ItemInfo) {
type DetailsEntry struct {
// TODO: `RepoRef` is currently the full path to the item in Kopia
// This can be optimized.
RepoRef string `json:"repoRef"`
RepoRef string `json:"repoRef"`
ShortRef string `json:"shortRef"`
ItemInfo
}
@ -120,7 +125,7 @@ func (de DetailsEntry) MinimumPrintable() any {
// Headers returns the human-readable names of properties in a DetailsEntry
// for printing out to a terminal in a columnar display.
func (de DetailsEntry) Headers() []string {
hs := []string{"Repo Ref"}
hs := []string{"Reference"}
if de.ItemInfo.Exchange != nil {
hs = append(hs, de.ItemInfo.Exchange.Headers()...)
@ -139,7 +144,7 @@ func (de DetailsEntry) Headers() []string {
// Values returns the values matching the Headers list.
func (de DetailsEntry) Values() []string {
vs := []string{de.RepoRef}
vs := []string{de.ShortRef}
if de.ItemInfo.Exchange != nil {
vs = append(vs, de.ItemInfo.Exchange.Values()...)

View File

@ -37,15 +37,17 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
{
name: "no info",
entry: details.DetailsEntry{
RepoRef: "reporef",
RepoRef: "reporef",
ShortRef: "deadbeef",
},
expectHs: []string{"Repo Ref"},
expectVs: []string{"reporef"},
expectHs: []string{"Reference"},
expectVs: []string{"deadbeef"},
},
{
name: "exchange event info",
entry: details.DetailsEntry{
RepoRef: "reporef",
RepoRef: "reporef",
ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{
Exchange: &details.ExchangeInfo{
ItemType: details.ExchangeEvent,
@ -56,13 +58,14 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
},
},
},
expectHs: []string{"Repo Ref", "Organizer", "Subject", "Starts", "Recurring"},
expectVs: []string{"reporef", "organizer", "subject", nowStr, "true"},
expectHs: []string{"Reference", "Organizer", "Subject", "Starts", "Recurring"},
expectVs: []string{"deadbeef", "organizer", "subject", nowStr, "true"},
},
{
name: "exchange contact info",
entry: details.DetailsEntry{
RepoRef: "reporef",
RepoRef: "reporef",
ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{
Exchange: &details.ExchangeInfo{
ItemType: details.ExchangeContact,
@ -70,13 +73,14 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
},
},
},
expectHs: []string{"Repo Ref", "Contact Name"},
expectVs: []string{"reporef", "contactName"},
expectHs: []string{"Reference", "Contact Name"},
expectVs: []string{"deadbeef", "contactName"},
},
{
name: "exchange mail info",
entry: details.DetailsEntry{
RepoRef: "reporef",
RepoRef: "reporef",
ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{
Exchange: &details.ExchangeInfo{
ItemType: details.ExchangeMail,
@ -86,24 +90,26 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
},
},
},
expectHs: []string{"Repo Ref", "Sender", "Subject", "Received"},
expectVs: []string{"reporef", "sender", "subject", nowStr},
expectHs: []string{"Reference", "Sender", "Subject", "Received"},
expectVs: []string{"deadbeef", "sender", "subject", nowStr},
},
{
name: "sharepoint info",
entry: details.DetailsEntry{
RepoRef: "reporef",
RepoRef: "reporef",
ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{
Sharepoint: &details.SharepointInfo{},
},
},
expectHs: []string{"Repo Ref"},
expectVs: []string{"reporef"},
expectHs: []string{"Reference"},
expectVs: []string{"deadbeef"},
},
{
name: "oneDrive info",
entry: details.DetailsEntry{
RepoRef: "reporef",
RepoRef: "reporef",
ShortRef: "deadbeef",
ItemInfo: details.ItemInfo{
OneDrive: &details.OneDriveInfo{
ItemName: "itemName",
@ -111,8 +117,8 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
},
},
},
expectHs: []string{"Repo Ref", "ItemName", "ParentPath"},
expectVs: []string{"reporef", "itemName", "parentPath"},
expectHs: []string{"Reference", "ItemName", "ParentPath"},
expectVs: []string{"deadbeef", "itemName", "parentPath"},
},
}