in cmd/list.go [217:335]
func (cooked cookedListCmdArgs) handleListContainerCommand() (err error) {
ctx := context.WithValue(context.TODO(), ste.ServiceAPIVersionOverride, ste.DefaultServiceApiVersion)
var credentialInfo common.CredentialInfo
source, err := SplitResourceString(cooked.sourcePath, cooked.location)
if err != nil {
return err
}
if err := common.VerifyIsURLResolvable(raw.src); cooked.location.IsRemote() && err != nil {
return fmt.Errorf("failed to resolve target: %w", err)
}
level, err := DetermineLocationLevel(source.Value, cooked.location, true)
if err != nil {
return err
}
// isSource is rather misnomer for canBePublic. We can list public containers, and hence isSource=true
if credentialInfo, _, err = GetCredentialInfoForLocation(ctx, cooked.location, source, true, common.CpkOptions{}); err != nil {
return fmt.Errorf("failed to obtain credential info: %s", err.Error())
} else if credentialInfo.CredentialType.IsAzureOAuth() {
uotm := GetUserOAuthTokenManagerInstance()
if tokenInfo, err := uotm.GetTokenInfo(ctx); err != nil {
return err
} else {
credentialInfo.OAuthTokenInfo = *tokenInfo
}
}
// check if user wants to get version id
getVersionId := containsProperty(cooked.properties, VersionId)
traverser, err := InitResourceTraverser(source, cooked.location, &ctx, &credentialInfo, common.ESymlinkHandlingType.Skip(), nil, true, true, false, common.EPermanentDeleteOption.None(), func(common.EntityType) {}, nil, false, common.ESyncHashType.None(), common.EPreservePermissionsOption.None(), common.LogNone, common.CpkOptions{}, nil, false, cooked.trailingDot, nil, nil, getVersionId)
if err != nil {
return fmt.Errorf("failed to initialize traverser: %s", err.Error())
}
var fileCount int64 = 0
var sizeCount int64 = 0
type versionIdObject struct {
versionId string
fileSize int64
}
objectVer := make(map[string]versionIdObject)
processor := func(object StoredObject) error {
lo := cooked.newListObject(object, level)
glcm.Output(func(format common.OutputFormat) string {
if format == common.EOutputFormat.Json() {
jsonOutput, err := json.Marshal(lo)
common.PanicIfErr(err)
return string(jsonOutput)
} else {
return lo.String()
}
}, common.EOutputMessageType.ListObject())
// ensure that versioned objects don't get counted multiple times in the tally
// 1. only include the size of the latest version of the object in the sizeCount
// 2. only include the object once in the fileCount
if cooked.RunningTally {
if getVersionId {
// get new version id object
updatedVersionId := versionIdObject{
versionId: object.blobVersionID,
fileSize: object.size,
}
// there exists a current version id of the object
if currentVersionId, ok := objectVer[object.relativePath]; ok {
// get current version id time
currentVid, _ := time.Parse(versionIdTimeFormat, currentVersionId.versionId)
// get new version id time
newVid, _ := time.Parse(versionIdTimeFormat, object.blobVersionID)
// if new vid came after the current vid, then it is the latest version
// update the objectVer with the latest version
// we will also remove sizeCount and fileCount of current object, allowing
// the updated sizeCount and fileCount to be added at line 320
if newVid.After(currentVid) {
sizeCount -= currentVersionId.fileSize // remove size of current object
fileCount-- // remove current object file count
objectVer[object.relativePath] = updatedVersionId
}
} else {
objectVer[object.relativePath] = updatedVersionId
}
}
fileCount++
sizeCount += object.size
}
return nil
}
err = traverser.Traverse(nil, processor, nil)
if err != nil {
return fmt.Errorf("failed to traverse container: %s", err.Error())
}
if cooked.RunningTally {
ls := cooked.newListSummary(fileCount, sizeCount)
glcm.Output(func(format common.OutputFormat) string {
if format == common.EOutputFormat.Json() {
jsonOutput, err := json.Marshal(ls)
common.PanicIfErr(err)
return string(jsonOutput)
} else {
return ls.String()
}
}, common.EOutputMessageType.ListSummary())
}
return nil
}