github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/kbfsedits/data_types.go (about)

     1  // Copyright 2018 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package kbfsedits
     6  
     7  import (
     8  	"time"
     9  
    10  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    11  	"github.com/keybase/client/go/kbfs/kbfsmd"
    12  	"github.com/keybase/client/go/kbfs/tlf"
    13  	"github.com/keybase/client/go/protocol/chat1"
    14  	"github.com/keybase/client/go/protocol/keybase1"
    15  )
    16  
    17  // NotificationVersion is the numeric version of the edit notification
    18  // data structure.
    19  type NotificationVersion int
    20  
    21  const (
    22  	// NotificationV1 is unused, but represents the original,
    23  	// MD-ops-based edit notification list.
    24  	NotificationV1 NotificationVersion = 1
    25  	// NotificationV2 is the first version that stores JSON-encoded
    26  	// notifications in chat messages.
    27  	NotificationV2 NotificationVersion = 2
    28  )
    29  
    30  // NotificationOpType indicates the type of the operation that caused
    31  // the notification.
    32  type NotificationOpType string
    33  
    34  const (
    35  	// NotificationCreate is the type of an edit notification
    36  	// representing a new file or directory creation.
    37  	NotificationCreate NotificationOpType = "create"
    38  	// NotificationModify is the type of an edit notification
    39  	// representing a file modification.
    40  	NotificationModify NotificationOpType = "modify"
    41  	// NotificationRename is the type of an edit notification
    42  	// representing a file or directory getting renamed.
    43  	NotificationRename NotificationOpType = "rename"
    44  	// NotificationDelete is the type of an edit notification
    45  	// representing a file or directory getting deleted.
    46  	NotificationDelete NotificationOpType = "delete"
    47  )
    48  
    49  // EntryType indicates the type of the file that was edited.
    50  type EntryType string
    51  
    52  const (
    53  	// EntryTypeFile is for files that have been edited.  Note that
    54  	// covers both regular files and executables.
    55  	EntryTypeFile EntryType = "file"
    56  	// EntryTypeDir is for directories that have been edited.
    57  	EntryTypeDir EntryType = "dir"
    58  	// EntryTypeSym is for symlinks that have been edited.
    59  	EntryTypeSym EntryType = "sym"
    60  )
    61  
    62  // ModifyRange represents a file modification.  Length is 0 for a
    63  // truncate.
    64  type ModifyRange struct {
    65  	Offset uint64
    66  	Length uint64
    67  }
    68  
    69  // NotificationParams is used for op-type-specific data.
    70  type NotificationParams struct {
    71  	OldFilename string        `json:",omitempty"` // for renames
    72  	Modifies    []ModifyRange `json:",omitempty"` // for modifies
    73  }
    74  
    75  // NotificationMessage is a summary of a single edit notification in
    76  // KBFS.  It is meant to be encoded and decoded with JSON.
    77  type NotificationMessage struct {
    78  	Version  NotificationVersion
    79  	Filename string
    80  	Type     NotificationOpType
    81  	Time     time.Time // server-reported time
    82  	FileType EntryType
    83  	Revision kbfsmd.Revision
    84  	Device   kbfscrypto.VerifyingKey
    85  	UID      keybase1.UID
    86  	FolderID tlf.ID
    87  	Params   *NotificationParams `json:",omitempty"`
    88  
    89  	// For internal sorting, not exported.
    90  	numWithinRevision int
    91  }
    92  
    93  // notificationsByRevision sorts NotificationMessages in reverse by
    94  // revision number.
    95  type notificationsByRevision []NotificationMessage
    96  
    97  func (nbr notificationsByRevision) Len() int {
    98  	return len(nbr)
    99  }
   100  
   101  func (nbr notificationsByRevision) Less(i, j int) bool {
   102  	// Reverse sort, so latest revisions come first.
   103  	if nbr[i].Revision > nbr[j].Revision {
   104  		return true
   105  	} else if nbr[i].Revision < nbr[j].Revision {
   106  		return false
   107  	}
   108  	// If they're equal, check the number within the revision.
   109  	return nbr[i].numWithinRevision > nbr[j].numWithinRevision
   110  }
   111  
   112  func (nbr notificationsByRevision) Swap(i, j int) {
   113  	nbr[i], nbr[j] = nbr[j], nbr[i]
   114  }
   115  
   116  // uniquify returns a shallow copy of `nbr` with duplicate
   117  // notifications (identified by their revision) removed.  It should
   118  // only be called on a presorted slice, and the returned slice is
   119  // guaranteed to remain sorted.
   120  func (nbr notificationsByRevision) uniquify() (ret notificationsByRevision) {
   121  	toSkip := make(map[int]bool)
   122  	for i, n := range nbr {
   123  		if i > 0 && n.Revision == nbr[i-1].Revision &&
   124  			n.numWithinRevision == nbr[i-1].numWithinRevision {
   125  			toSkip[i] = true
   126  		}
   127  	}
   128  
   129  	if len(toSkip) == 0 {
   130  		return nbr
   131  	}
   132  
   133  	ret = make(notificationsByRevision, 0, len(nbr)-len(toSkip))
   134  	for i, n := range nbr {
   135  		if !toSkip[i] {
   136  			ret = append(ret, n)
   137  		}
   138  	}
   139  	return ret
   140  }
   141  
   142  // SelfWriteMessage is written into a special, private channel when
   143  // the user writes to some TLF.
   144  type SelfWriteMessage struct {
   145  	Version    NotificationVersion
   146  	Folder     keybase1.Folder
   147  	ConvID     chat1.ConversationID
   148  	ServerTime time.Time
   149  }