get details working (and other cleanup)

details wasn't properly listing backed up items.  This fixes
the details display, and contains some code clean-up that occurred
along the way.
This commit is contained in:
ryanfkeepers 2024-01-24 15:17:14 -07:00
parent 4cba77343a
commit 14817de592
16 changed files with 78 additions and 147 deletions

View File

@ -213,7 +213,6 @@ func runDetailsTeamsChatsCmd(cmd *cobra.Command) error {
opts := utils.MakeTeamsChatsOpts(cmd)
sel := utils.IncludeTeamsChatsRestoreDataSelectors(ctx, opts)
sel.Configure(selectors.Config{OnlyMatchItemNames: true})
utils.FilterTeamsChatsRestoreInfoSelectors(sel, opts)
ds, err := genericDetailsCommand(cmd, flags.BackupIDFV, sel.Selector)

View File

@ -89,7 +89,10 @@ func IncludeTeamsChatsRestoreDataSelectors(ctx context.Context, opts TeamsChatsO
users = selectors.Any()
}
return selectors.NewTeamsChatsRestore(users)
sel := selectors.NewTeamsChatsRestore(users)
sel.Include(sel.Chats(selectors.Any()))
return sel
}
// FilterTeamsChatsRestoreInfoSelectors builds the common info-selector filters.

View File

@ -115,11 +115,8 @@ func populateCollection[I chatsItemer](
)
ctx = clues.AddLabelCounter(ctx, cl.PlainAdder())
cc := api.CallConfig{
CanMakeDeltaQueries: false,
}
items, err := bh.getItemIDs(ctx, cc)
items, err := bh.getItemIDs(ctx)
if err != nil {
errs.AddRecoverable(ctx, clues.Stack(err))
return collection, clues.Stack(errs.Failure()).OrNil()

View File

@ -49,14 +49,6 @@ type mockBackupHandler struct {
doNotInclude bool
}
//lint:ignore U1000 false linter issue due to generics
func (bh mockBackupHandler) augmentItemInfo(
*details.TeamsChatsInfo,
models.Chatable,
) {
// no-op
}
func (bh mockBackupHandler) container() container[models.Chatable] {
return chatContainer()
}
@ -71,7 +63,6 @@ func (bh mockBackupHandler) getContainer(
func (bh mockBackupHandler) getItemIDs(
_ context.Context,
_ api.CallConfig,
) ([]models.Chatable, error) {
return bh.chats, bh.chatsErr
}

View File

@ -46,8 +46,11 @@ func (bh usersChatsBackupHandler) getContainer(
//lint:ignore U1000 required for interface compliance
func (bh usersChatsBackupHandler) getItemIDs(
ctx context.Context,
cc api.CallConfig,
) ([]models.Chatable, error) {
cc := api.CallConfig{
Expand: []string{"lastMessagePreview"},
}
return bh.ac.GetChats(
ctx,
bh.protectedResourceID,
@ -89,11 +92,7 @@ func (bh usersChatsBackupHandler) getItem(
chatID := ptr.Val(chat.GetId())
cc := api.CallConfig{
Expand: []string{"lastMessagePreview"},
}
msgs, err := bh.ac.GetChatMessages(ctx, chatID, cc)
msgs, err := bh.ac.GetChatMessages(ctx, chatID, api.CallConfig{})
if err != nil {
return nil, nil, clues.Stack(err)
}
@ -103,14 +102,6 @@ func (bh usersChatsBackupHandler) getItem(
return chat, api.TeamsChatInfo(chat), nil
}
//lint:ignore U1000 false linter issue due to generics
func (bh usersChatsBackupHandler) augmentItemInfo(
dgi *details.TeamsChatsInfo,
c models.Chatable,
) {
// no-op
}
func chatContainer() container[models.Chatable] {
return container[models.Chatable]{
storageDirFolders: path.Elements{},

View File

@ -66,7 +66,7 @@ func updateStatus(
// or notMoved (if they match).
func NewCollection[I chatsItemer](
baseCol data.BaseCollection,
getAndAugment getItemAndAugmentInfoer[I],
getter getItemer[I],
protectedResource string,
items []I,
contains container[I],
@ -76,7 +76,7 @@ func NewCollection[I chatsItemer](
BaseCollection: baseCol,
items: items,
contains: contains,
getAndAugment: getAndAugment,
getter: getter,
statusUpdater: statusUpdater,
stream: make(chan data.Item, collectionChannelBufferSize),
protectedResource: protectedResource,
@ -96,7 +96,7 @@ type lazyFetchCollection[I chatsItemer] struct {
items []I
getAndAugment getItemAndAugmentInfoer[I]
getter getItemer[I]
statusUpdater support.StatusUpdater
}
@ -167,13 +167,13 @@ func (col *lazyFetchCollection[I]) streamItems(ctx context.Context, errs *fault.
col.stream <- data.NewLazyItemWithInfo(
ictx,
&lazyItemGetter[I]{
modTime: modTime,
getAndAugment: col.getAndAugment,
resourceID: col.protectedResource,
item: item,
containerIDs: col.FullPath().Folders(),
contains: col.contains,
parentPath: col.LocationPath().String(),
modTime: modTime,
getter: col.getter,
resourceID: col.protectedResource,
item: item,
containerIDs: col.FullPath().Folders(),
contains: col.contains,
parentPath: col.LocationPath().String(),
},
itemID,
modTime,
@ -192,13 +192,13 @@ func (col *lazyFetchCollection[I]) streamItems(ctx context.Context, errs *fault.
}
type lazyItemGetter[I chatsItemer] struct {
getAndAugment getItemAndAugmentInfoer[I]
resourceID string
item I
parentPath string
containerIDs path.Elements
modTime time.Time
contains container[I]
getter getItemer[I]
resourceID string
item I
parentPath string
containerIDs path.Elements
modTime time.Time
contains container[I]
}
func (lig *lazyItemGetter[I]) GetData(
@ -208,7 +208,7 @@ func (lig *lazyItemGetter[I]) GetData(
writer := kjson.NewJsonSerializationWriter()
defer writer.Close()
item, info, err := lig.getAndAugment.getItem(
item, info, err := lig.getter.getItem(
ctx,
lig.resourceID,
lig.item)
@ -229,8 +229,6 @@ func (lig *lazyItemGetter[I]) GetData(
return nil, nil, false, err
}
lig.getAndAugment.augmentItemInfo(info, lig.contains.container)
if err := writer.WriteObjectValue("", item); err != nil {
err = clues.WrapWC(ctx, err, "writing item to serializer").Label(fault.LabelForceNoBackupCreation)
errs.AddRecoverable(ctx, err)

View File

@ -163,11 +163,6 @@ func (m getAndAugmentChat) getItem(
return chat, &details.TeamsChatsInfo{}, m.err
}
//lint:ignore U1000 false linter issue due to generics
func (getAndAugmentChat) augmentItemInfo(*details.TeamsChatsInfo, models.Chatable) {
// no-op
}
func (suite *CollectionUnitSuite) TestLazyFetchCollection_Items_LazyFetch() {
var (
t = suite.T()
@ -225,7 +220,7 @@ func (suite *CollectionUnitSuite) TestLazyFetchCollection_Items_LazyFetch() {
count.New()),
items: test.items,
contains: container[models.Chatable]{},
getAndAugment: getterAugmenter,
getter: getterAugmenter,
stream: make(chan data.Item),
statusUpdater: statusUpdater,
}
@ -285,11 +280,11 @@ func (suite *CollectionUnitSuite) TestLazyItem_GetDataErrors() {
li := data.NewLazyItemWithInfo(
ctx,
&lazyItemGetter[models.Chatable]{
resourceID: "resourceID",
item: chat,
getAndAugment: &m,
modTime: now,
parentPath: parentPath,
resourceID: "resourceID",
item: chat,
getter: &m,
modTime: now,
parentPath: parentPath,
},
ptr.Val(chat.GetId()),
now,
@ -329,11 +324,11 @@ func (suite *CollectionUnitSuite) TestLazyItem_ReturnsEmptyReaderOnDeletedInFlig
li := data.NewLazyItemWithInfo(
ctx,
&lazyItemGetter[models.Chatable]{
resourceID: "resourceID",
item: chat,
getAndAugment: &m,
modTime: now,
parentPath: parentPath,
resourceID: "resourceID",
item: chat,
getter: &m,
modTime: now,
parentPath: parentPath,
},
ptr.Val(chat.GetId()),
now,
@ -368,11 +363,11 @@ func (suite *CollectionUnitSuite) TestLazyItem() {
li := data.NewLazyItemWithInfo(
ctx,
&lazyItemGetter[models.Chatable]{
resourceID: "resourceID",
item: chat,
getAndAugment: &m,
modTime: now,
parentPath: parentPath,
resourceID: "resourceID",
item: chat,
getter: &m,
modTime: now,
parentPath: parentPath,
},
ptr.Val(chat.GetId()),
now,

View File

@ -22,7 +22,7 @@ type chatsItemer interface {
type backupHandler[I chatsItemer] interface {
getContainerer[I]
getItemAndAugmentInfoer[I]
getItemer[I]
getItemer[I]
getItemIDser[I]
includeItemer[I]
@ -39,22 +39,10 @@ type getContainerer[I chatsItemer] interface {
) (container[I], error)
}
type getItemAndAugmentInfoer[I chatsItemer] interface {
getItemer[I]
augmentItemInfoer[I]
}
type augmentItemInfoer[I chatsItemer] interface {
// augmentItemInfo completes the teamChatsInfo population with any data
// owned by the container and not accessible to the item.
augmentItemInfo(*details.TeamsChatsInfo, I)
}
// gets all item IDs in the container
type getItemIDser[I chatsItemer] interface {
getItemIDs(
ctx context.Context,
cc api.CallConfig,
) ([]I, error)
}

View File

@ -141,26 +141,23 @@ func (de Entry) 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 Entry) Headers(skipID bool) []string {
hs := []string{}
var hs []string
if de.ItemInfo.Folder != nil {
switch {
case de.ItemInfo.Folder != nil:
hs = de.ItemInfo.Folder.Headers()
}
if de.ItemInfo.Exchange != nil {
case de.ItemInfo.Exchange != nil:
hs = de.ItemInfo.Exchange.Headers()
}
if de.ItemInfo.SharePoint != nil {
case de.ItemInfo.SharePoint != nil:
hs = de.ItemInfo.SharePoint.Headers()
}
if de.ItemInfo.OneDrive != nil {
case de.ItemInfo.OneDrive != nil:
hs = de.ItemInfo.OneDrive.Headers()
}
if de.ItemInfo.Groups != nil {
case de.ItemInfo.Groups != nil:
hs = de.ItemInfo.Groups.Headers()
case de.ItemInfo.TeamsChats != nil:
hs = de.ItemInfo.TeamsChats.Headers()
default:
hs = []string{"ERROR - Service not recognized"}
}
if skipID {
@ -172,26 +169,23 @@ func (de Entry) Headers(skipID bool) []string {
// Values returns the values matching the Headers list.
func (de Entry) Values(skipID bool) []string {
vs := []string{}
var vs []string
if de.ItemInfo.Folder != nil {
switch {
case de.ItemInfo.Folder != nil:
vs = de.ItemInfo.Folder.Values()
}
if de.ItemInfo.Exchange != nil {
case de.ItemInfo.Exchange != nil:
vs = de.ItemInfo.Exchange.Values()
}
if de.ItemInfo.SharePoint != nil {
case de.ItemInfo.SharePoint != nil:
vs = de.ItemInfo.SharePoint.Values()
}
if de.ItemInfo.OneDrive != nil {
case de.ItemInfo.OneDrive != nil:
vs = de.ItemInfo.OneDrive.Values()
}
if de.ItemInfo.Groups != nil {
case de.ItemInfo.Groups != nil:
vs = de.ItemInfo.Groups.Values()
case de.ItemInfo.TeamsChats != nil:
vs = de.ItemInfo.TeamsChats.Values()
default:
vs = []string{"ERROR - Service not recognized"}
}
if skipID {

View File

@ -91,19 +91,14 @@ func (i ItemInfo) infoType() ItemType {
switch {
case i.Folder != nil:
return i.Folder.ItemType
case i.Exchange != nil:
return i.Exchange.ItemType
case i.SharePoint != nil:
return i.SharePoint.ItemType
case i.OneDrive != nil:
return i.OneDrive.ItemType
case i.Groups != nil:
return i.Groups.ItemType
case i.TeamsChats != nil:
return i.TeamsChats.ItemType
}
@ -115,19 +110,14 @@ func (i ItemInfo) size() int64 {
switch {
case i.Exchange != nil:
return i.Exchange.Size
case i.OneDrive != nil:
return i.OneDrive.Size
case i.SharePoint != nil:
return i.SharePoint.Size
case i.Groups != nil:
return i.Groups.Size
case i.Folder != nil:
return i.Folder.Size
case i.TeamsChats != nil:
return int64(i.TeamsChats.Chat.MessageCount)
}
@ -139,19 +129,14 @@ func (i ItemInfo) Modified() time.Time {
switch {
case i.Exchange != nil:
return i.Exchange.Modified
case i.OneDrive != nil:
return i.OneDrive.Modified
case i.SharePoint != nil:
return i.SharePoint.Modified
case i.Groups != nil:
return i.Groups.Modified
case i.Folder != nil:
return i.Folder.Modified
case i.TeamsChats != nil:
return i.TeamsChats.Modified
}
@ -163,19 +148,14 @@ func (i ItemInfo) uniqueLocation(baseLoc *path.Builder) (*uniqueLoc, error) {
switch {
case i.Exchange != nil:
return i.Exchange.uniqueLocation(baseLoc)
case i.OneDrive != nil:
return i.OneDrive.uniqueLocation(baseLoc)
case i.SharePoint != nil:
return i.SharePoint.uniqueLocation(baseLoc)
case i.Groups != nil:
return i.Groups.uniqueLocation(baseLoc)
case i.TeamsChats != nil:
return i.TeamsChats.uniqueLocation(baseLoc)
default:
return nil, clues.New("unsupported type")
}
@ -185,19 +165,14 @@ func (i ItemInfo) updateFolder(f *FolderInfo) error {
switch {
case i.Exchange != nil:
return i.Exchange.updateFolder(f)
case i.OneDrive != nil:
return i.OneDrive.updateFolder(f)
case i.SharePoint != nil:
return i.SharePoint.updateFolder(f)
case i.Groups != nil:
return i.Groups.updateFolder(f)
case i.TeamsChats != nil:
return i.TeamsChats.updateFolder(f)
default:
return clues.New("unsupported type")
}

View File

@ -44,7 +44,7 @@ type ChatInfo struct {
LastMessagePreview string `json:"preview,omitempty"`
Members []string `json:"members,omitempty"`
MessageCount int `json:"size,omitempty"`
Name string `json:"name,omitempty"`
Topic string `json:"topic,omitempty"`
}
// Headers returns the human-readable names of properties in a ChatsInfo
@ -52,7 +52,7 @@ type ChatInfo struct {
func (i TeamsChatsInfo) Headers() []string {
switch i.ItemType {
case TeamsChat:
return []string{"Name", "Last message", "Last message at", "Message count", "Created", "Members"}
return []string{"Topic", "Last message", "Last message at", "Message count", "Created", "Members"}
}
return []string{}
@ -75,7 +75,7 @@ func (i TeamsChatsInfo) Values() []string {
}
return []string{
i.Chat.Name,
i.Chat.Topic,
i.Chat.LastMessagePreview,
dttm.FormatToTabularDisplay(i.Chat.LastMessageAt),
strconv.Itoa(i.Chat.MessageCount),

View File

@ -42,7 +42,7 @@ func (suite *ChatsUnitSuite) TestChatsPrintable() {
LastMessagePreview: "last message preview",
Members: []string{"foo@bar.baz", "fnords@smarf.zoomba"},
MessageCount: 42,
Name: "chat name",
Topic: "chat name",
},
},
expectHs: []string{"Name", "Last message", "Last message at", "Message count", "Created", "Members"},

View File

@ -506,7 +506,7 @@ func (s TeamsChatsScope) matchesInfo(dii details.ItemInfo) bool {
case TeamsChatsInfoChatMember:
i = strings.Join(info.Chat.Members, ",")
case TeamsChatsInfoChatName:
i = info.Chat.Name
i = info.Chat.Topic
}
return s.Matches(infoCat, i)

View File

@ -273,7 +273,7 @@ func (suite *TeamsChatsSelectorSuite) TestTeamsChatsScope_MatchesInfo() {
LastMessagePreview: "preview",
Members: []string{member},
MessageCount: 1,
Name: name,
Topic: name,
},
},
}

View File

@ -103,7 +103,7 @@ func TeamsChatInfo(chat models.Chatable) *details.TeamsChatsInfo {
LastMessagePreview: preview,
Members: memberNames,
MessageCount: len(msgs),
Name: ptr.Val(chat.GetTopic()),
Topic: ptr.Val(chat.GetTopic()),
},
}
}

View File

@ -64,7 +64,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() {
ItemType: details.TeamsChat,
Modified: then,
Chat: details.ChatInfo{
Name: "Hello world",
Topic: "Hello world",
LastMessageAt: then,
LastMessagePreview: id,
Members: []string{},
@ -92,7 +92,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() {
ItemType: details.TeamsChat,
Modified: then,
Chat: details.ChatInfo{
Name: "Hello world",
Topic: "Hello world",
LastMessageAt: then,
LastMessagePreview: id,
Members: []string{},
@ -120,7 +120,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() {
ItemType: details.TeamsChat,
Modified: then,
Chat: details.ChatInfo{
Name: "Hello world",
Topic: "Hello world",
LastMessageAt: time.Time{},
LastMessagePreview: "",
Members: []string{},
@ -138,7 +138,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() {
chat, expected := test.expected()
result := TeamsChatInfo(chat)
assert.Equal(t, expected.Chat.Name, result.Chat.Name)
assert.Equal(t, expected.Chat.Topic, result.Chat.Topic)
expectCreated := chat.GetCreatedDateTime()
if expectCreated != nil {