Skip to content

Commit ee1c683

Browse files
[GitHub] azcopy list with versionids does not show version id (#2550)
* fixing list version property and added test * only add vid when intended, add test for multi-versions * addressing feedback * handle running tally + updates to test with running tally * handling edge case, handling edge case in test, updates to code * adding additional version to multiversions test * updating running tally code to account for latest versions only * cleaning up code * call containsProperty once * making sizeCount and fileCount update dynamically and smartly * addressing comments * minor update to test
1 parent 06b1fb3 commit ee1c683

13 files changed

+439
-12
lines changed

cmd/copyEnumeratorInit.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (cca *CookedCopyCmdArgs) initEnumerator(jobPartOrder common.CopyJobPartOrde
7272
jobPartOrder.S2SPreserveBlobTags = cca.S2sPreserveBlobTags
7373

7474
dest := cca.FromTo.To()
75-
traverser, err = InitResourceTraverser(cca.Source, cca.FromTo.From(), &ctx, &srcCredInfo, cca.SymlinkHandling, cca.ListOfFilesChannel, cca.Recursive, getRemoteProperties, cca.IncludeDirectoryStubs, cca.permanentDeleteOption, func(common.EntityType) {}, cca.ListOfVersionIDs, cca.S2sPreserveBlobTags, common.ESyncHashType.None(), cca.preservePermissions, azcopyLogVerbosity, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, &dest, cca.excludeContainer)
75+
traverser, err = InitResourceTraverser(cca.Source, cca.FromTo.From(), &ctx, &srcCredInfo, cca.SymlinkHandling, cca.ListOfFilesChannel, cca.Recursive, getRemoteProperties, cca.IncludeDirectoryStubs, cca.permanentDeleteOption, func(common.EntityType) {}, cca.ListOfVersionIDs, cca.S2sPreserveBlobTags, common.ESyncHashType.None(), cca.preservePermissions, azcopyLogVerbosity, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, &dest, cca.excludeContainer, false)
7676

7777
if err != nil {
7878
return nil, err
@@ -343,7 +343,7 @@ func (cca *CookedCopyCmdArgs) isDestDirectory(dst common.ResourceString, ctx *co
343343
return false
344344
}
345345

346-
rt, err := InitResourceTraverser(dst, cca.FromTo.To(), ctx, &dstCredInfo, common.ESymlinkHandlingType.Skip(), nil, false, false, false, common.EPermanentDeleteOption.None(), func(common.EntityType) {}, cca.ListOfVersionIDs, false, common.ESyncHashType.None(), cca.preservePermissions, common.LogNone, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, nil, cca.excludeContainer)
346+
rt, err := InitResourceTraverser(dst, cca.FromTo.To(), ctx, &dstCredInfo, common.ESymlinkHandlingType.Skip(), nil, false, false, false, common.EPermanentDeleteOption.None(), func(common.EntityType) {}, cca.ListOfVersionIDs, false, common.ESyncHashType.None(), cca.preservePermissions, common.LogNone, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, nil, cca.excludeContainer, false)
347347

348348
if err != nil {
349349
return false

cmd/copyEnumeratorInit_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,4 @@ func TestValidateSourceWithWildCard(t *testing.T) {
162162
err := cca.validateSourceDir(blobTraverser)
163163
a.Nil(err)
164164
a.False(cca.IsSourceDir)
165-
}
165+
}

cmd/list.go

+51-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"fmt"
2828
"strconv"
2929
"strings"
30+
"time"
3031

3132
"github.com/spf13/cobra"
3233

@@ -59,8 +60,20 @@ const (
5960
leaseDuration validProperty = "LeaseDuration"
6061
leaseStatus validProperty = "LeaseStatus"
6162
archiveStatus validProperty = "ArchiveStatus"
63+
64+
versionIdTimeFormat = "2006-01-02T15:04:05.9999999Z"
6265
)
6366

67+
// containsProperty checks if the property array contains a valid property
68+
func containsProperty(properties []validProperty, prop validProperty) bool {
69+
for _, item := range properties {
70+
if item == prop {
71+
return true
72+
}
73+
}
74+
return false
75+
}
76+
6477
// validProperties returns an array of possible values for the validProperty const type.
6578
func validProperties() []validProperty {
6679
return []validProperty{lastModifiedTime, versionId, blobType, blobAccessTier,
@@ -237,7 +250,10 @@ func (cooked cookedListCmdArgs) HandleListContainerCommand() (err error) {
237250
}
238251
}
239252

240-
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)
253+
// check if user wants to get version id
254+
shouldGetVersionId := containsProperty(cooked.properties, versionId)
255+
256+
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, shouldGetVersionId)
241257

242258
if err != nil {
243259
return fmt.Errorf("failed to initialize traverser: %s", err.Error())
@@ -246,6 +262,12 @@ func (cooked cookedListCmdArgs) HandleListContainerCommand() (err error) {
246262
var fileCount int64 = 0
247263
var sizeCount int64 = 0
248264

265+
type versionIdObject struct {
266+
versionId string
267+
fileSize int64
268+
}
269+
objectVer := make(map[string]versionIdObject)
270+
249271
processor := func(object StoredObject) error {
250272
path := object.relativePath
251273
if object.entityType == common.EEntityType.Folder() {
@@ -266,6 +288,34 @@ func (cooked cookedListCmdArgs) HandleListContainerCommand() (err error) {
266288
}
267289

268290
if cooked.RunningTally {
291+
if shouldGetVersionId {
292+
// get new version id object
293+
updatedVersionId := versionIdObject{
294+
versionId: object.blobVersionID,
295+
fileSize: object.size,
296+
}
297+
298+
// there exists a current version id of the object
299+
if currentVersionId, ok := objectVer[object.relativePath]; ok {
300+
// get current version id time
301+
currentVid, _ := time.Parse(versionIdTimeFormat, currentVersionId.versionId)
302+
303+
// get new version id time
304+
newVid, _ := time.Parse(versionIdTimeFormat, object.blobVersionID)
305+
306+
// if new vid came after the current vid, then it is the latest version
307+
// update the objectVer with the latest version
308+
// we will also remove sizeCount and fileCount of current object, allowing
309+
// the updated sizeCount and fileCount to be added at line 320
310+
if newVid.After(currentVid) {
311+
sizeCount -= currentVersionId.fileSize // remove size of current object
312+
fileCount-- // remove current object file count
313+
objectVer[object.relativePath] = updatedVersionId
314+
}
315+
} else {
316+
objectVer[object.relativePath] = updatedVersionId
317+
}
318+
}
269319
fileCount++
270320
sizeCount += object.size
271321
}

cmd/removeEnumerator.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func newRemoveEnumerator(cca *CookedCopyCmdArgs) (enumerator *CopyEnumerator, er
5050
ctx := context.WithValue(context.TODO(), ste.ServiceAPIVersionOverride, ste.DefaultServiceApiVersion)
5151

5252
// Include-path is handled by ListOfFilesChannel.
53-
sourceTraverser, err = InitResourceTraverser(cca.Source, cca.FromTo.From(), &ctx, &cca.credentialInfo, common.ESymlinkHandlingType.Skip(), cca.ListOfFilesChannel, cca.Recursive, true, cca.IncludeDirectoryStubs, cca.permanentDeleteOption, func(common.EntityType) {}, cca.ListOfVersionIDs, false, common.ESyncHashType.None(), common.EPreservePermissionsOption.None(), azcopyLogVerbosity, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, nil, cca.excludeContainer)
53+
sourceTraverser, err = InitResourceTraverser(cca.Source, cca.FromTo.From(), &ctx, &cca.credentialInfo, common.ESymlinkHandlingType.Skip(), cca.ListOfFilesChannel, cca.Recursive, true, cca.IncludeDirectoryStubs, cca.permanentDeleteOption, func(common.EntityType) {}, cca.ListOfVersionIDs, false, common.ESyncHashType.None(), common.EPreservePermissionsOption.None(), azcopyLogVerbosity, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, nil, cca.excludeContainer, false)
5454

5555
// report failure to create traverser
5656
if err != nil {

cmd/setPropertiesEnumerator.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func setPropertiesEnumerator(cca *CookedCopyCmdArgs) (enumerator *CopyEnumerator
4646
}
4747

4848
// Include-path is handled by ListOfFilesChannel.
49-
sourceTraverser, err = InitResourceTraverser(cca.Source, cca.FromTo.From(), &ctx, &cca.credentialInfo, common.ESymlinkHandlingType.Preserve(), cca.ListOfFilesChannel, cca.Recursive, false, cca.IncludeDirectoryStubs, cca.permanentDeleteOption, func(common.EntityType) {}, cca.ListOfVersionIDs, false, common.ESyncHashType.None(), common.EPreservePermissionsOption.None(), azcopyLogVerbosity, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, nil, cca.excludeContainer)
49+
sourceTraverser, err = InitResourceTraverser(cca.Source, cca.FromTo.From(), &ctx, &cca.credentialInfo, common.ESymlinkHandlingType.Preserve(), cca.ListOfFilesChannel, cca.Recursive, false, cca.IncludeDirectoryStubs, cca.permanentDeleteOption, func(common.EntityType) {}, cca.ListOfVersionIDs, false, common.ESyncHashType.None(), common.EPreservePermissionsOption.None(), azcopyLogVerbosity, cca.CpkOptions, nil, cca.StripTopDir, cca.trailingDot, nil, cca.excludeContainer, false)
5050

5151
// report failure to create traverser
5252
if err != nil {

cmd/syncEnumerator.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (cca *cookedSyncCmdArgs) initEnumerator(ctx context.Context) (enumerator *s
6464
if entityType == common.EEntityType.File() {
6565
atomic.AddUint64(&cca.atomicSourceFilesScanned, 1)
6666
}
67-
}, nil, cca.s2sPreserveBlobTags, cca.compareHash, cca.preservePermissions, azcopyLogVerbosity, cca.cpkOptions, nil, false, cca.trailingDot, &dest, nil)
67+
}, nil, cca.s2sPreserveBlobTags, cca.compareHash, cca.preservePermissions, azcopyLogVerbosity, cca.cpkOptions, nil, false, cca.trailingDot, &dest, nil, false)
6868

6969
if err != nil {
7070
return nil, err
@@ -85,7 +85,7 @@ func (cca *cookedSyncCmdArgs) initEnumerator(ctx context.Context) (enumerator *s
8585
if entityType == common.EEntityType.File() {
8686
atomic.AddUint64(&cca.atomicDestinationFilesScanned, 1)
8787
}
88-
}, nil, cca.s2sPreserveBlobTags, cca.compareHash, cca.preservePermissions, azcopyLogVerbosity, cca.cpkOptions, nil, false, cca.trailingDot, nil, nil)
88+
}, nil, cca.s2sPreserveBlobTags, cca.compareHash, cca.preservePermissions, azcopyLogVerbosity, cca.cpkOptions, nil, false, cca.trailingDot, nil, nil, false)
8989
if err != nil {
9090
return nil, err
9191
}

cmd/zc_enumerator.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ type enumerationCounterFunc func(entityType common.EntityType)
334334
// errorOnDirWOutRecursive is used by copy.
335335
// If errorChannel is non-nil, all errors encountered during enumeration will be conveyed through this channel.
336336
// To avoid slowdowns, use a buffered channel of enough capacity.
337-
func InitResourceTraverser(resource common.ResourceString, location common.Location, ctx *context.Context, credential *common.CredentialInfo, symlinkHandling common.SymlinkHandlingType, listOfFilesChannel chan string, recursive, getProperties, includeDirectoryStubs bool, permanentDeleteOption common.PermanentDeleteOption, incrementEnumerationCounter enumerationCounterFunc, listOfVersionIds chan string, s2sPreserveBlobTags bool, syncHashType common.SyncHashType, preservePermissions common.PreservePermissionsOption, logLevel common.LogLevel, cpkOptions common.CpkOptions, errorChannel chan ErrorFileInfo, stripTopDir bool, trailingDot common.TrailingDotOption, destination *common.Location, excludeContainerNames []string) (ResourceTraverser, error) {
337+
func InitResourceTraverser(resource common.ResourceString, location common.Location, ctx *context.Context, credential *common.CredentialInfo, symlinkHandling common.SymlinkHandlingType, listOfFilesChannel chan string, recursive, getProperties, includeDirectoryStubs bool, permanentDeleteOption common.PermanentDeleteOption, incrementEnumerationCounter enumerationCounterFunc, listOfVersionIds chan string, s2sPreserveBlobTags bool, syncHashType common.SyncHashType, preservePermissions common.PreservePermissionsOption, logLevel common.LogLevel, cpkOptions common.CpkOptions, errorChannel chan ErrorFileInfo, stripTopDir bool, trailingDot common.TrailingDotOption, destination *common.Location, excludeContainerNames []string, includeVersionsList bool) (ResourceTraverser, error) {
338338
var output ResourceTraverser
339339

340340
var includeDeleted bool
@@ -353,6 +353,10 @@ func InitResourceTraverser(resource common.ResourceString, location common.Locat
353353
includeVersion = true
354354
}
355355

356+
// print out version id when using azcopy list
357+
if includeVersionsList {
358+
includeVersion = true
359+
}
356360
// Clean up the resource if it's a local path
357361
if location == common.ELocation.Local() {
358362
resource = common.ResourceString{Value: cleanLocalPath(resource.ValueLocal())}

cmd/zc_traverser_blob.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ func (t *blobTraverser) createStoredObjectForBlob(preprocessor objectMorpher, bl
476476
object.blobDeleted = common.IffNotNil(blobInfo.Deleted, false)
477477
if t.includeDeleted && t.includeSnapshot {
478478
object.blobSnapshotID = common.IffNotNil(blobInfo.Snapshot, "")
479-
} else if t.includeDeleted && t.includeVersion && blobInfo.VersionID != nil {
479+
} else if t.includeVersion && blobInfo.VersionID != nil {
480480
object.blobVersionID = common.IffNotNil(blobInfo.VersionID, "")
481481
}
482482
return object

cmd/zc_traverser_list.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func newListTraverser(parent common.ResourceString, parentType common.Location,
107107
}
108108

109109
// Construct a traverser that goes through the child
110-
traverser, err := InitResourceTraverser(source, parentType, ctx, credential, handleSymlinks, nil, recursive, getProperties, includeDirectoryStubs, common.EPermanentDeleteOption.None(), incrementEnumerationCounter, nil, s2sPreserveBlobTags, syncHashType, preservePermissions, logLevel, cpkOptions, nil, false, trailingDot, destination, nil)
110+
traverser, err := InitResourceTraverser(source, parentType, ctx, credential, handleSymlinks, nil, recursive, getProperties, includeDirectoryStubs, common.EPermanentDeleteOption.None(), incrementEnumerationCounter, nil, s2sPreserveBlobTags, syncHashType, preservePermissions, logLevel, cpkOptions, nil, false, trailingDot, destination, nil, false)
111111
if err != nil {
112112
return nil, err
113113
}

cmd/zt_generic_traverser_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ func TestLocalWildcardOverlap(t *testing.T) {
104104
common.ETrailingDotOption.Enable(),
105105
nil,
106106
nil,
107+
false,
107108
)
108109
a.Nil(err)
109110

0 commit comments

Comments
 (0)