mirror of
				https://github.com/rclone/rclone.git
				synced 2025-10-30 23:17:59 +02:00 
			
		
		
		
	Create fs.Directory interface and use it everywhere
This commit is contained in:
		| @@ -426,12 +426,8 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 			case folderKind: | ||||
| 				// cache the directory ID for later lookups | ||||
| 				f.dirCache.Put(remote, *node.Id) | ||||
| 				d := &fs.Dir{ | ||||
| 					Name:  remote, | ||||
| 					Bytes: -1, | ||||
| 					Count: -1, | ||||
| 				} | ||||
| 				d.When, _ = time.Parse(timeFormat, *node.ModifiedDate) // FIXME | ||||
| 				when, _ := time.Parse(timeFormat, *node.ModifiedDate) // FIXME | ||||
| 				d := fs.NewDir(remote, when) | ||||
| 				entries = append(entries, d) | ||||
| 			case fileKind: | ||||
| 				o, err := f.newObjectWithInfo(remote, node) | ||||
|   | ||||
							
								
								
									
										12
									
								
								b2/b2.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								b2/b2.go
									
									
									
									
									
								
							| @@ -521,11 +521,7 @@ func (f *Fs) list(dir string, recurse bool, prefix string, limit int, hidden boo | ||||
| // Convert a list item into a DirEntry | ||||
| func (f *Fs) itemToDirEntry(remote string, object *api.File, isDirectory bool, last *string) (fs.DirEntry, error) { | ||||
| 	if isDirectory { | ||||
| 		d := &fs.Dir{ | ||||
| 			Name:  remote, | ||||
| 			Bytes: -1, | ||||
| 			Count: -1, | ||||
| 		} | ||||
| 		d := fs.NewDir(remote, time.Time{}) | ||||
| 		return d, nil | ||||
| 	} | ||||
| 	if remote == *last { | ||||
| @@ -569,11 +565,7 @@ func (f *Fs) listBuckets(dir string) (entries fs.DirEntries, err error) { | ||||
| 		return nil, fs.ErrorListBucketRequired | ||||
| 	} | ||||
| 	err = f.listBucketsToFn(func(bucket *api.Bucket) error { | ||||
| 		d := &fs.Dir{ | ||||
| 			Name:  bucket.Name, | ||||
| 			Bytes: -1, | ||||
| 			Count: -1, | ||||
| 		} | ||||
| 		d := fs.NewDir(bucket.Name, time.Time{}) | ||||
| 		entries = append(entries, d) | ||||
| 		return nil | ||||
| 	}) | ||||
|   | ||||
| @@ -32,7 +32,7 @@ var commandDefintion = &cobra.Command{ | ||||
| 					return nil | ||||
| 				} | ||||
| 				for _, entry := range entries { | ||||
| 					_, isDir := entry.(*fs.Dir) | ||||
| 					_, isDir := entry.(fs.Directory) | ||||
| 					if isDir { | ||||
| 						fmt.Println(entry.Remote() + "/") | ||||
| 					} else { | ||||
|   | ||||
| @@ -99,7 +99,7 @@ can be processed line by line as each item is written one to a line. | ||||
| 						item.ModTime = Timestamp(entry.ModTime()) | ||||
| 					} | ||||
| 					switch x := entry.(type) { | ||||
| 					case *fs.Dir: | ||||
| 					case fs.Directory: | ||||
| 						item.IsDir = true | ||||
| 					case fs.Object: | ||||
| 						item.IsDir = false | ||||
|   | ||||
| @@ -118,7 +118,7 @@ func (d *Dir) ReadDirAll(ctx context.Context) (dirents []fuse.Dirent, err error) | ||||
| 				Type: fuse.DT_File, | ||||
| 				Name: path.Base(x.Remote()), | ||||
| 			} | ||||
| 		case *fs.Dir: | ||||
| 		case fs.Directory: | ||||
| 			dirent = fuse.Dirent{ | ||||
| 				// Inode FIXME ??? | ||||
| 				Type: fuse.DT_Dir, | ||||
|   | ||||
| @@ -32,12 +32,12 @@ type Dir struct { | ||||
| 	items   map[string]*DirEntry | ||||
| } | ||||
|  | ||||
| func newDir(fsys *FS, f fs.Fs, fsDir *fs.Dir) *Dir { | ||||
| func newDir(fsys *FS, f fs.Fs, fsDir fs.Directory) *Dir { | ||||
| 	return &Dir{ | ||||
| 		fsys:    fsys, | ||||
| 		f:       f, | ||||
| 		path:    fsDir.Name, | ||||
| 		modTime: fsDir.When, | ||||
| 		path:    fsDir.Remote(), | ||||
| 		modTime: fsDir.ModTime(), | ||||
| 		inode:   NewInode(), | ||||
| 	} | ||||
| } | ||||
| @@ -113,10 +113,10 @@ func (d *Dir) walk(absPath string, fun func(*Dir)) { | ||||
| // | ||||
| // Reset the directory to new state, discarding all the objects and | ||||
| // reading everything again | ||||
| func (d *Dir) rename(newParent *Dir, fsDir *fs.Dir) { | ||||
| func (d *Dir) rename(newParent *Dir, fsDir fs.Directory) { | ||||
| 	d.ForgetAll() | ||||
| 	d.path = fsDir.Name | ||||
| 	d.modTime = fsDir.When | ||||
| 	d.path = fsDir.Remote() | ||||
| 	d.modTime = fsDir.ModTime() | ||||
| 	d.read = time.Time{} | ||||
| } | ||||
|  | ||||
| @@ -180,12 +180,12 @@ func (d *Dir) readDir() error { | ||||
| 				Obj:  obj, | ||||
| 				Node: nil, | ||||
| 			} | ||||
| 		case *fs.Dir: | ||||
| 		case fs.Directory: | ||||
| 			dir := item | ||||
| 			name := path.Base(dir.Remote()) | ||||
| 			// Use old dir value if it exists | ||||
| 			if oldItem, ok := oldItems[name]; ok { | ||||
| 				if _, ok := oldItem.Obj.(*fs.Dir); ok { | ||||
| 				if _, ok := oldItem.Obj.(fs.Directory); ok { | ||||
| 					d.items[name] = oldItem | ||||
| 					continue | ||||
| 				} | ||||
| @@ -262,7 +262,7 @@ func (d *Dir) lookupNode(leaf string) (item *DirEntry, err error) { | ||||
| 	switch x := item.Obj.(type) { | ||||
| 	case fs.Object: | ||||
| 		node, err = newFile(d, x, leaf), nil | ||||
| 	case *fs.Dir: | ||||
| 	case fs.Directory: | ||||
| 		node, err = newDir(d.fsys, d.f, x), nil | ||||
| 	default: | ||||
| 		err = errors.Errorf("unknown type %T", item) | ||||
| @@ -342,10 +342,7 @@ func (d *Dir) Mkdir(name string) (*Dir, error) { | ||||
| 		fs.Errorf(path, "Dir.Mkdir failed to create directory: %v", err) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	fsDir := &fs.Dir{ | ||||
| 		Name: path, | ||||
| 		When: time.Now(), | ||||
| 	} | ||||
| 	fsDir := fs.NewDir(path, time.Now()) | ||||
| 	dir := newDir(d.fsys, d.f, fsDir) | ||||
| 	d.addObject(fsDir, dir) | ||||
| 	// fs.Debugf(path, "Dir.Mkdir OK") | ||||
| @@ -373,7 +370,7 @@ func (d *Dir) Remove(name string) error { | ||||
| 			fs.Errorf(path, "Dir.Remove file error: %v", err) | ||||
| 			return err | ||||
| 		} | ||||
| 	case *fs.Dir: | ||||
| 	case fs.Directory: | ||||
| 		// Check directory is empty first | ||||
| 		dir := item.Node.(*Dir) | ||||
| 		empty, err := dir.isEmpty() | ||||
| @@ -440,23 +437,21 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error { | ||||
| 				oldFile.rename(destDir, newObject) | ||||
| 			} | ||||
| 		} | ||||
| 	case *fs.Dir: | ||||
| 	case fs.Directory: | ||||
| 		doDirMove := d.f.Features().DirMove | ||||
| 		if doDirMove == nil { | ||||
| 			err := errors.Errorf("Fs %q can't rename directories (no DirMove)", d.f) | ||||
| 			fs.Errorf(oldPath, "Dir.Rename error: %v", err) | ||||
| 			return err | ||||
| 		} | ||||
| 		srcRemote := x.Name | ||||
| 		srcRemote := x.Remote() | ||||
| 		dstRemote := newPath | ||||
| 		err = doDirMove(d.f, srcRemote, dstRemote) | ||||
| 		if err != nil { | ||||
| 			fs.Errorf(oldPath, "Dir.Rename error: %v", err) | ||||
| 			return err | ||||
| 		} | ||||
| 		newDir := new(fs.Dir) | ||||
| 		*newDir = *x | ||||
| 		newDir.Name = newPath | ||||
| 		newDir := fs.NewDirCopy(x).SetRemote(newPath) | ||||
| 		newObj = newDir | ||||
| 		// Update the node with the new details | ||||
| 		if oldNode != nil { | ||||
|   | ||||
| @@ -45,10 +45,7 @@ type FS struct { | ||||
|  | ||||
| // NewFS creates a new filing system and root directory | ||||
| func NewFS(f fs.Fs) *FS { | ||||
| 	fsDir := &fs.Dir{ | ||||
| 		Name: "", | ||||
| 		When: time.Now(), | ||||
| 	} | ||||
| 	fsDir := fs.NewDir("", time.Now()) | ||||
| 	fsys := &FS{ | ||||
| 		f: f, | ||||
| 	} | ||||
|   | ||||
| @@ -80,7 +80,7 @@ func (d *Dir) Entries() fs.DirEntries { | ||||
| // Call with d.mu held | ||||
| func (d *Dir) getDir(i int) (subDir *Dir, isDir bool) { | ||||
| 	obj := d.entries[i] | ||||
| 	dir, ok := obj.(*fs.Dir) | ||||
| 	dir, ok := obj.(fs.Directory) | ||||
| 	if !ok { | ||||
| 		return nil, false | ||||
| 	} | ||||
|   | ||||
| @@ -157,8 +157,8 @@ func (f *Fs) add(entries *fs.DirEntries, obj fs.Object) { | ||||
| } | ||||
|  | ||||
| // Encrypt an directory file name to entries. | ||||
| func (f *Fs) addDir(entries *fs.DirEntries, dir *fs.Dir) { | ||||
| 	remote := dir.Name | ||||
| func (f *Fs) addDir(entries *fs.DirEntries, dir fs.Directory) { | ||||
| 	remote := dir.Remote() | ||||
| 	decryptedRemote, err := f.cipher.DecryptDirName(remote) | ||||
| 	if err != nil { | ||||
| 		fs.Debugf(remote, "Skipping undecryptable dir name: %v", err) | ||||
| @@ -177,7 +177,7 @@ func (f *Fs) encryptEntries(entries fs.DirEntries) (newEntries fs.DirEntries, er | ||||
| 		switch x := entry.(type) { | ||||
| 		case fs.Object: | ||||
| 			f.add(&newEntries, x) | ||||
| 		case *fs.Dir: | ||||
| 		case fs.Directory: | ||||
| 			f.addDir(&newEntries, x) | ||||
| 		default: | ||||
| 			return nil, errors.Errorf("Unknown object type %T", entry) | ||||
| @@ -545,16 +545,16 @@ func (o *Object) Update(in io.Reader, src fs.ObjectInfo, options ...fs.OpenOptio | ||||
| } | ||||
|  | ||||
| // newDir returns a dir with the Name decrypted | ||||
| func (f *Fs) newDir(dir *fs.Dir) *fs.Dir { | ||||
| 	new := *dir | ||||
| 	remote := dir.Name | ||||
| func (f *Fs) newDir(dir fs.Directory) fs.Directory { | ||||
| 	new := fs.NewDirCopy(dir) | ||||
| 	remote := dir.Remote() | ||||
| 	decryptedRemote, err := f.cipher.DecryptDirName(remote) | ||||
| 	if err != nil { | ||||
| 		fs.Debugf(remote, "Undecryptable dir name: %v", err) | ||||
| 	} else { | ||||
| 		new.Name = decryptedRemote | ||||
| 		new.SetRemote(decryptedRemote) | ||||
| 	} | ||||
| 	return &new | ||||
| 	return new | ||||
| } | ||||
|  | ||||
| // ObjectInfo describes a wrapped fs.ObjectInfo for being the source | ||||
|   | ||||
| @@ -586,12 +586,8 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 		case item.MimeType == driveFolderType: | ||||
| 			// cache the directory ID for later lookups | ||||
| 			f.dirCache.Put(remote, item.Id) | ||||
| 			d := &fs.Dir{ | ||||
| 				Name:  remote, | ||||
| 				Bytes: -1, | ||||
| 				Count: -1, | ||||
| 			} | ||||
| 			d.When, _ = time.Parse(timeFormatIn, item.ModifiedDate) | ||||
| 			when, _ := time.Parse(timeFormatIn, item.ModifiedDate) | ||||
| 			d := fs.NewDir(remote, when) | ||||
| 			entries = append(entries, d) | ||||
| 		case item.Md5Checksum != "" || item.FileSize > 0: | ||||
| 			// If item has MD5 sum or a length it is a file stored on drive | ||||
|   | ||||
| @@ -392,13 +392,7 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 				} | ||||
| 				name = strings.Trim(name, "/") | ||||
| 				if name != "" && name != dir { | ||||
| 					d := &fs.Dir{ | ||||
| 						Name: name, | ||||
| 						When: time.Now(), | ||||
| 						//When:  folderInfo.ClientMtime, | ||||
| 						//Bytes: folderInfo.Bytes, | ||||
| 						//Count: -1, | ||||
| 					} | ||||
| 					d := fs.NewDir(name, time.Now()) | ||||
| 					entries = append(entries, d) | ||||
| 				} | ||||
| 			} else if fileInfo != nil { | ||||
|   | ||||
							
								
								
									
										85
									
								
								fs/dir.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								fs/dir.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| package fs | ||||
|  | ||||
| import "time" | ||||
|  | ||||
| // Dir describes an unspecialized directory for directory/container/bucket lists | ||||
| type Dir struct { | ||||
| 	remote  string    // name of the directory | ||||
| 	modTime time.Time // modification or creation time - IsZero for unknown | ||||
| 	size    int64     // size of directory and contents or -1 if unknown | ||||
| 	items   int64     // number of objects or -1 for unknown | ||||
| } | ||||
|  | ||||
| // NewDir creates an unspecialized Directory object | ||||
| func NewDir(remote string, modTime time.Time) *Dir { | ||||
| 	return &Dir{ | ||||
| 		remote:  remote, | ||||
| 		modTime: modTime, | ||||
| 		size:    -1, | ||||
| 		items:   -1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewDirCopy creates an unspecialized copy of the Directory object passed in | ||||
| func NewDirCopy(d Directory) *Dir { | ||||
| 	return &Dir{ | ||||
| 		remote:  d.Remote(), | ||||
| 		modTime: d.ModTime(), | ||||
| 		size:    d.Size(), | ||||
| 		items:   d.Items(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // String returns the name | ||||
| func (d *Dir) String() string { | ||||
| 	return d.remote | ||||
| } | ||||
|  | ||||
| // Remote returns the remote path | ||||
| func (d *Dir) Remote() string { | ||||
| 	return d.remote | ||||
| } | ||||
|  | ||||
| // SetRemote sets the remote | ||||
| func (d *Dir) SetRemote(remote string) *Dir { | ||||
| 	d.remote = remote | ||||
| 	return d | ||||
| } | ||||
|  | ||||
| // ModTime returns the modification date of the file | ||||
| // It should return a best guess if one isn't available | ||||
| func (d *Dir) ModTime() time.Time { | ||||
| 	if !d.modTime.IsZero() { | ||||
| 		return d.modTime | ||||
| 	} | ||||
| 	return time.Now() | ||||
| } | ||||
|  | ||||
| // Size returns the size of the file | ||||
| func (d *Dir) Size() int64 { | ||||
| 	return d.size | ||||
| } | ||||
|  | ||||
| // SetSize sets the size of the directory | ||||
| func (d *Dir) SetSize(size int64) *Dir { | ||||
| 	d.size = size | ||||
| 	return d | ||||
| } | ||||
|  | ||||
| // Items returns the count of items in this directory or this | ||||
| // directory and subdirectories if known, -1 for unknown | ||||
| func (d *Dir) Items() int64 { | ||||
| 	return d.items | ||||
| } | ||||
|  | ||||
| // SetItems sets the number of items in the directory | ||||
| func (d *Dir) SetItems(items int64) *Dir { | ||||
| 	d.items = items | ||||
| 	return d | ||||
| } | ||||
|  | ||||
| // Check interfaces | ||||
| var ( | ||||
| 	_ DirEntry  = (*Dir)(nil) | ||||
| 	_ Directory = (*Dir)(nil) | ||||
| ) | ||||
							
								
								
									
										91
									
								
								fs/fs.go
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								fs/fs.go
									
									
									
									
									
								
							| @@ -209,6 +209,15 @@ type DirEntry interface { | ||||
| 	Size() int64 | ||||
| } | ||||
|  | ||||
| // Directory is a filesystem like directory provided by an Fs | ||||
| type Directory interface { | ||||
| 	DirEntry | ||||
|  | ||||
| 	// Items returns the count of items in this directory or this | ||||
| 	// directory and subdirectories if known, -1 for unknown | ||||
| 	Items() int64 | ||||
| } | ||||
|  | ||||
| // MimeTyper is an optional interface for Object | ||||
| type MimeTyper interface { | ||||
| 	// MimeType returns the content type of the Object if | ||||
| @@ -544,41 +553,6 @@ type ObjectPair struct { | ||||
| // ObjectPairChan is a channel of ObjectPair | ||||
| type ObjectPairChan chan ObjectPair | ||||
|  | ||||
| // Dir describes a directory for directory/container/bucket lists | ||||
| type Dir struct { | ||||
| 	Name  string    // name of the directory | ||||
| 	When  time.Time // modification or creation time - IsZero for unknown | ||||
| 	Bytes int64     // size of directory and contents -1 for unknown | ||||
| 	Count int64     // number of objects -1 for unknown | ||||
| } | ||||
|  | ||||
| // String returns the name | ||||
| func (d *Dir) String() string { | ||||
| 	return d.Name | ||||
| } | ||||
|  | ||||
| // Remote returns the remote path | ||||
| func (d *Dir) Remote() string { | ||||
| 	return d.Name | ||||
| } | ||||
|  | ||||
| // ModTime returns the modification date of the file | ||||
| // It should return a best guess if one isn't available | ||||
| func (d *Dir) ModTime() time.Time { | ||||
| 	if !d.When.IsZero() { | ||||
| 		return d.When | ||||
| 	} | ||||
| 	return time.Now() | ||||
| } | ||||
|  | ||||
| // Size returns the size of the file | ||||
| func (d *Dir) Size() int64 { | ||||
| 	return d.Bytes | ||||
| } | ||||
|  | ||||
| // Check interface | ||||
| var _ DirEntry = (*Dir)(nil) | ||||
|  | ||||
| // Find looks for an Info object for the name passed in | ||||
| // | ||||
| // Services are looked up in the config file | ||||
| @@ -651,50 +625,3 @@ func CheckClose(c io.Closer, err *error) { | ||||
| 		*err = cerr | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewStaticObjectInfo returns a static ObjectInfo | ||||
| // If hashes is nil and fs is not nil, the hash map will be replaced with | ||||
| // empty hashes of the types supported by the fs. | ||||
| func NewStaticObjectInfo(remote string, modTime time.Time, size int64, storable bool, hashes map[HashType]string, fs Info) ObjectInfo { | ||||
| 	info := &staticObjectInfo{ | ||||
| 		remote:   remote, | ||||
| 		modTime:  modTime, | ||||
| 		size:     size, | ||||
| 		storable: storable, | ||||
| 		hashes:   hashes, | ||||
| 		fs:       fs, | ||||
| 	} | ||||
| 	if fs != nil && hashes == nil { | ||||
| 		set := fs.Hashes().Array() | ||||
| 		info.hashes = make(map[HashType]string) | ||||
| 		for _, ht := range set { | ||||
| 			info.hashes[ht] = "" | ||||
| 		} | ||||
| 	} | ||||
| 	return info | ||||
| } | ||||
|  | ||||
| type staticObjectInfo struct { | ||||
| 	remote   string | ||||
| 	modTime  time.Time | ||||
| 	size     int64 | ||||
| 	storable bool | ||||
| 	hashes   map[HashType]string | ||||
| 	fs       Info | ||||
| } | ||||
|  | ||||
| func (i *staticObjectInfo) Fs() Info           { return i.fs } | ||||
| func (i *staticObjectInfo) Remote() string     { return i.remote } | ||||
| func (i *staticObjectInfo) String() string     { return i.remote } | ||||
| func (i *staticObjectInfo) ModTime() time.Time { return i.modTime } | ||||
| func (i *staticObjectInfo) Size() int64        { return i.size } | ||||
| func (i *staticObjectInfo) Storable() bool     { return i.storable } | ||||
| func (i *staticObjectInfo) Hash(h HashType) (string, error) { | ||||
| 	if len(i.hashes) == 0 { | ||||
| 		return "", ErrHashUnsupported | ||||
| 	} | ||||
| 	if hash, ok := i.hashes[h]; ok { | ||||
| 		return hash, nil | ||||
| 	} | ||||
| 	return "", ErrHashUnsupported | ||||
| } | ||||
|   | ||||
							
								
								
									
										50
									
								
								fs/object.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								fs/object.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| package fs | ||||
|  | ||||
| import "time" | ||||
|  | ||||
| // NewStaticObjectInfo returns a static ObjectInfo | ||||
| // If hashes is nil and fs is not nil, the hash map will be replaced with | ||||
| // empty hashes of the types supported by the fs. | ||||
| func NewStaticObjectInfo(remote string, modTime time.Time, size int64, storable bool, hashes map[HashType]string, fs Info) ObjectInfo { | ||||
| 	info := &staticObjectInfo{ | ||||
| 		remote:   remote, | ||||
| 		modTime:  modTime, | ||||
| 		size:     size, | ||||
| 		storable: storable, | ||||
| 		hashes:   hashes, | ||||
| 		fs:       fs, | ||||
| 	} | ||||
| 	if fs != nil && hashes == nil { | ||||
| 		set := fs.Hashes().Array() | ||||
| 		info.hashes = make(map[HashType]string) | ||||
| 		for _, ht := range set { | ||||
| 			info.hashes[ht] = "" | ||||
| 		} | ||||
| 	} | ||||
| 	return info | ||||
| } | ||||
|  | ||||
| type staticObjectInfo struct { | ||||
| 	remote   string | ||||
| 	modTime  time.Time | ||||
| 	size     int64 | ||||
| 	storable bool | ||||
| 	hashes   map[HashType]string | ||||
| 	fs       Info | ||||
| } | ||||
|  | ||||
| func (i *staticObjectInfo) Fs() Info           { return i.fs } | ||||
| func (i *staticObjectInfo) Remote() string     { return i.remote } | ||||
| func (i *staticObjectInfo) String() string     { return i.remote } | ||||
| func (i *staticObjectInfo) ModTime() time.Time { return i.modTime } | ||||
| func (i *staticObjectInfo) Size() int64        { return i.size } | ||||
| func (i *staticObjectInfo) Storable() bool     { return i.storable } | ||||
| func (i *staticObjectInfo) Hash(h HashType) (string, error) { | ||||
| 	if len(i.hashes) == 0 { | ||||
| 		return "", ErrHashUnsupported | ||||
| 	} | ||||
| 	if hash, ok := i.hashes[h]; ok { | ||||
| 		return hash, nil | ||||
| 	} | ||||
| 	return "", ErrHashUnsupported | ||||
| } | ||||
| @@ -566,20 +566,20 @@ func (ds DirEntries) ForObjectError(fn func(o Object) error) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ForDir runs the function supplied on every object in the entries | ||||
| func (ds DirEntries) ForDir(fn func(dir *Dir)) { | ||||
| // ForDir runs the function supplied on every Directory in the entries | ||||
| func (ds DirEntries) ForDir(fn func(dir Directory)) { | ||||
| 	for _, entry := range ds { | ||||
| 		dir, ok := entry.(*Dir) | ||||
| 		dir, ok := entry.(Directory) | ||||
| 		if ok { | ||||
| 			fn(dir) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ForDirError runs the function supplied on every object in the entries | ||||
| func (ds DirEntries) ForDirError(fn func(dir *Dir) error) error { | ||||
| // ForDirError runs the function supplied on every Directory in the entries | ||||
| func (ds DirEntries) ForDirError(fn func(dir Directory) error) error { | ||||
| 	for _, entry := range ds { | ||||
| 		dir, ok := entry.(*Dir) | ||||
| 		dir, ok := entry.(Directory) | ||||
| 		if ok { | ||||
| 			err := fn(dir) | ||||
| 			if err != nil { | ||||
| @@ -617,7 +617,7 @@ func ListDirSorted(fs Fs, includeAll bool, dir string) (entries DirEntries, err | ||||
| 				} else { | ||||
| 					Debugf(x, "Excluded from sync (and deletion)") | ||||
| 				} | ||||
| 			case *Dir: | ||||
| 			case Directory: | ||||
| 				if Config.Filter.IncludeDirectory(x.Remote()) { | ||||
| 					newEntries = append(newEntries, entry) | ||||
| 				} else { | ||||
| @@ -1052,9 +1052,9 @@ func ListDir(f Fs, w io.Writer) error { | ||||
| 			// FIXME count errors and carry on for listing | ||||
| 			return err | ||||
| 		} | ||||
| 		entries.ForDir(func(dir *Dir) { | ||||
| 		entries.ForDir(func(dir Directory) { | ||||
| 			if dir != nil { | ||||
| 				syncFprintf(w, "%12d %13s %9d %s\n", dir.Bytes, dir.When.Format("2006-01-02 15:04:05"), dir.Count, dir.Name) | ||||
| 				syncFprintf(w, "%12d %13s %9d %s\n", dir.Size(), dir.ModTime().Format("2006-01-02 15:04:05"), dir.Items(), dir.Remote()) | ||||
| 			} | ||||
| 		}) | ||||
| 		return nil | ||||
| @@ -1478,9 +1478,9 @@ func Rmdirs(f Fs, dir string) error { | ||||
| 		} | ||||
| 		for _, entry := range entries { | ||||
| 			switch x := entry.(type) { | ||||
| 			case *Dir: | ||||
| 			case Directory: | ||||
| 				// add a new directory as empty | ||||
| 				dir := x.Name | ||||
| 				dir := x.Remote() | ||||
| 				_, found := dirEmpty[dir] | ||||
| 				if !found { | ||||
| 					dirEmpty[dir] = true | ||||
|   | ||||
| @@ -172,7 +172,7 @@ func NewRun(t *testing.T) *Run { | ||||
| 						if err != nil { | ||||
| 							t.Errorf("Error removing file %q: %v", x.Remote(), err) | ||||
| 						} | ||||
| 					case *fs.Dir: | ||||
| 					case fs.Directory: | ||||
| 						toDelete = append(toDelete, x.Remote()) | ||||
| 					} | ||||
| 				} | ||||
| @@ -959,7 +959,7 @@ func TestListDirSorted(t *testing.T) { | ||||
| 		name := item.Remote() | ||||
| 		switch item.(type) { | ||||
| 		case fs.Object: | ||||
| 		case *fs.Dir: | ||||
| 		case fs.Directory: | ||||
| 			name += "/" | ||||
| 		default: | ||||
| 			t.Fatalf("Unknown type %+v", item) | ||||
|   | ||||
| @@ -755,7 +755,7 @@ func (s *syncCopyMove) dstOnly(dst DirEntry, job listDirJob, jobs *[]listDirJob) | ||||
| 		default: | ||||
| 			panic(fmt.Sprintf("unexpected delete mode %d", s.deleteMode)) | ||||
| 		} | ||||
| 	case *Dir: | ||||
| 	case Directory: | ||||
| 		// Do the same thing to the entire contents of the directory | ||||
| 		if job.dstDepth > 0 { | ||||
| 			*jobs = append(*jobs, listDirJob{ | ||||
| @@ -784,7 +784,7 @@ func (s *syncCopyMove) srcOnly(src DirEntry, job listDirJob, jobs *[]listDirJob) | ||||
| 			// No need to check since doesn't exist | ||||
| 			s.toBeUploaded <- ObjectPair{x, nil} | ||||
| 		} | ||||
| 	case *Dir: | ||||
| 	case Directory: | ||||
| 		// Do the same thing to the entire contents of the directory | ||||
| 		if job.srcDepth > 0 { | ||||
| 			*jobs = append(*jobs, listDirJob{ | ||||
| @@ -814,9 +814,9 @@ func (s *syncCopyMove) transfer(dst, src DirEntry, job listDirJob, jobs *[]listD | ||||
| 			Errorf(dst, "%v", err) | ||||
| 			s.processError(err) | ||||
| 		} | ||||
| 	case *Dir: | ||||
| 	case Directory: | ||||
| 		// Do the same thing to the entire contents of the directory | ||||
| 		_, ok := dst.(*Dir) | ||||
| 		_, ok := dst.(Directory) | ||||
| 		if ok { | ||||
| 			if job.srcDepth > 0 && job.dstDepth > 0 { | ||||
| 				*jobs = append(*jobs, listDirJob{ | ||||
|   | ||||
							
								
								
									
										15
									
								
								fs/walk.go
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								fs/walk.go
									
									
									
									
									
								
							| @@ -9,6 +9,7 @@ import ( | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
| @@ -119,7 +120,7 @@ func walk(f Fs, path string, includeAll bool, maxLevel int, fn WalkFunc, listDir | ||||
| 					entries, err := listDir(f, includeAll, job.remote) | ||||
| 					var jobs []listJob | ||||
| 					if err == nil && job.depth != 0 { | ||||
| 						entries.ForDir(func(dir *Dir) { | ||||
| 						entries.ForDir(func(dir Directory) { | ||||
| 							// Recurse for the directory | ||||
| 							jobs = append(jobs, listJob{ | ||||
| 								remote: dir.Remote(), | ||||
| @@ -214,9 +215,7 @@ func (dt DirTree) checkParent(root, dirPath string) { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	dt[parentPath] = append(entries, &Dir{ | ||||
| 		Name: dirPath, | ||||
| 	}) | ||||
| 	dt[parentPath] = append(entries, NewDir(dirPath, time.Now())) | ||||
| 	dt.checkParent(root, parentPath) | ||||
| } | ||||
|  | ||||
| @@ -250,7 +249,7 @@ func (dt DirTree) String() string { | ||||
| 		fmt.Fprintf(out, "%s/\n", dir) | ||||
| 		for _, entry := range dt[dir] { | ||||
| 			flag := "" | ||||
| 			if _, ok := entry.(*Dir); ok { | ||||
| 			if _, ok := entry.(Directory); ok { | ||||
| 				flag = "/" | ||||
| 			} | ||||
| 			fmt.Fprintf(out, "  %s%s\n", path.Base(entry.Remote()), flag) | ||||
| @@ -284,7 +283,7 @@ func walkRDirTree(f Fs, path string, includeAll bool, maxLevel int, listR ListRF | ||||
| 				} else { | ||||
| 					Debugf(x, "Excluded from sync (and deletion)") | ||||
| 				} | ||||
| 			case *Dir: | ||||
| 			case Directory: | ||||
| 				if includeAll || Config.Filter.IncludeDirectory(x.Remote()) { | ||||
| 					if maxLevel < 0 || slashes <= maxLevel-1 { | ||||
| 						if slashes == maxLevel-1 { | ||||
| @@ -359,7 +358,7 @@ func walkR(f Fs, path string, includeAll bool, maxLevel int, fn WalkFunc, listR | ||||
| } | ||||
|  | ||||
| // WalkGetAll runs Walk getting all the results | ||||
| func WalkGetAll(f Fs, path string, includeAll bool, maxLevel int) (objs []Object, dirs []*Dir, err error) { | ||||
| func WalkGetAll(f Fs, path string, includeAll bool, maxLevel int) (objs []Object, dirs []Directory, err error) { | ||||
| 	err = Walk(f, path, includeAll, maxLevel, func(dirPath string, entries DirEntries, err error) error { | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| @@ -368,7 +367,7 @@ func WalkGetAll(f Fs, path string, includeAll bool, maxLevel int) (objs []Object | ||||
| 			switch x := entry.(type) { | ||||
| 			case Object: | ||||
| 				objs = append(objs, x) | ||||
| 			case *Dir: | ||||
| 			case Directory: | ||||
| 				dirs = append(dirs, x) | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -177,8 +177,8 @@ func (ls *listDirs) WalkR() { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newDir(name string) *Dir { | ||||
| 	return &Dir{Name: name} | ||||
| func newDir(name string) Directory { | ||||
| 	return NewDir(name, time.Time{}) | ||||
| } | ||||
|  | ||||
| func testWalkEmpty(t *testing.T) *listDirs { | ||||
|   | ||||
| @@ -184,7 +184,7 @@ func CheckListingWithPrecision(t *testing.T, f fs.Fs, items []Item, expectedDirs | ||||
| 	is := NewItems(items) | ||||
| 	oldErrors := fs.Stats.GetErrors() | ||||
| 	var objs []fs.Object | ||||
| 	var dirs []*fs.Dir | ||||
| 	var dirs []fs.Directory | ||||
| 	var err error | ||||
| 	var retries = *ListRetries | ||||
| 	sleep := time.Second / 2 | ||||
| @@ -231,7 +231,7 @@ func CheckListingWithPrecision(t *testing.T, f fs.Fs, items []Item, expectedDirs | ||||
| 	if expectedDirs != nil && len(dirs) != 0 { | ||||
| 		actualDirs := []string{} | ||||
| 		for _, dir := range dirs { | ||||
| 			actualDirs = append(actualDirs, dir.Name) | ||||
| 			actualDirs = append(actualDirs, dir.Remote()) | ||||
| 		} | ||||
| 		sort.Strings(actualDirs) | ||||
| 		sort.Strings(expectedDirs) | ||||
|   | ||||
| @@ -183,10 +183,10 @@ func winPath(s string) string { | ||||
| } | ||||
|  | ||||
| // dirsToNames returns a sorted list of names | ||||
| func dirsToNames(dirs []*fs.Dir) []string { | ||||
| func dirsToNames(dirs []fs.Directory) []string { | ||||
| 	names := []string{} | ||||
| 	for _, dir := range dirs { | ||||
| 		names = append(names, winPath(dir.Name)) | ||||
| 		names = append(names, winPath(dir.Remote())) | ||||
| 	} | ||||
| 	sort.Strings(names) | ||||
| 	return names | ||||
| @@ -399,7 +399,7 @@ func TestFsListSubdir(t *testing.T) { | ||||
| 	fileName := file2.Path | ||||
| 	var err error | ||||
| 	var objs []fs.Object | ||||
| 	var dirs []*fs.Dir | ||||
| 	var dirs []fs.Directory | ||||
| 	for i := 0; i < 2; i++ { | ||||
| 		dir, _ := path.Split(fileName) | ||||
| 		dir = dir[:len(dir)-1] | ||||
|   | ||||
| @@ -324,12 +324,7 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 			if object.Name == "." || object.Name == ".." { | ||||
| 				continue | ||||
| 			} | ||||
| 			d := &fs.Dir{ | ||||
| 				Name:  newremote, | ||||
| 				When:  object.Time, | ||||
| 				Bytes: 0, | ||||
| 				Count: -1, | ||||
| 			} | ||||
| 			d := fs.NewDir(newremote, object.Time) | ||||
| 			entries = append(entries, d) | ||||
| 		default: | ||||
| 			o := &Object{ | ||||
|   | ||||
| @@ -363,11 +363,7 @@ func (f *Fs) list(dir string, recurse bool, fn listFn) error { | ||||
| // Convert a list item into a DirEntry | ||||
| func (f *Fs) itemToDirEntry(remote string, object *storage.Object, isDirectory bool) (fs.DirEntry, error) { | ||||
| 	if isDirectory { | ||||
| 		d := &fs.Dir{ | ||||
| 			Name:  remote, | ||||
| 			Bytes: int64(object.Size), | ||||
| 			Count: 0, | ||||
| 		} | ||||
| 		d := fs.NewDir(remote, time.Time{}).SetSize(int64(object.Size)) | ||||
| 		return d, nil | ||||
| 	} | ||||
| 	o, err := f.newObjectWithInfo(remote, object) | ||||
| @@ -411,11 +407,7 @@ func (f *Fs) listBuckets(dir string) (entries fs.DirEntries, err error) { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		for _, bucket := range buckets.Items { | ||||
| 			d := &fs.Dir{ | ||||
| 				Name:  bucket.Name, | ||||
| 				Bytes: 0, | ||||
| 				Count: 0, | ||||
| 			} | ||||
| 			d := fs.NewDir(bucket.Name, time.Time{}) | ||||
| 			entries = append(entries, d) | ||||
| 		} | ||||
| 		if buckets.NextPageToken == "" { | ||||
|   | ||||
| @@ -307,12 +307,7 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 		name = strings.TrimRight(name, "/") | ||||
| 		remote := path.Join(dir, name) | ||||
| 		if isDir { | ||||
| 			dir := &fs.Dir{ | ||||
| 				Name:  remote, | ||||
| 				When:  timeUnset, | ||||
| 				Bytes: 0, | ||||
| 				Count: 0, | ||||
| 			} | ||||
| 			dir := fs.NewDir(remote, timeUnset) | ||||
| 			entries = append(entries, dir) | ||||
| 		} else { | ||||
| 			file := &Object{ | ||||
|   | ||||
| @@ -67,8 +67,8 @@ func testListRoot(t *testing.T, f fs.Fs) { | ||||
|  | ||||
| 	e := entries[0] | ||||
| 	assert.Equal(t, "four", e.Remote()) | ||||
| 	assert.Equal(t, int64(0), e.Size()) | ||||
| 	_, ok := e.(*fs.Dir) | ||||
| 	assert.Equal(t, int64(-1), e.Size()) | ||||
| 	_, ok := e.(fs.Directory) | ||||
| 	assert.True(t, ok) | ||||
|  | ||||
| 	e = entries[1] | ||||
| @@ -79,8 +79,8 @@ func testListRoot(t *testing.T, f fs.Fs) { | ||||
|  | ||||
| 	e = entries[2] | ||||
| 	assert.Equal(t, "three", e.Remote()) | ||||
| 	assert.Equal(t, int64(0), e.Size()) | ||||
| 	_, ok = e.(*fs.Dir) | ||||
| 	assert.Equal(t, int64(-1), e.Size()) | ||||
| 	_, ok = e.(fs.Directory) | ||||
| 	assert.True(t, ok) | ||||
|  | ||||
| 	e = entries[3] | ||||
|   | ||||
| @@ -236,12 +236,7 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 				// Ignore directories which are symlinks.  These are junction points under windows which | ||||
| 				// are kind of a souped up symlink. Unix doesn't have directories which are symlinks. | ||||
| 				if (mode&os.ModeSymlink) == 0 && f.dev == readDevice(fi) { | ||||
| 					d := &fs.Dir{ | ||||
| 						Name:  f.dirNames.Save(newRemote, f.cleanRemote(newRemote)), | ||||
| 						When:  fi.ModTime(), | ||||
| 						Bytes: 0, | ||||
| 						Count: 0, | ||||
| 					} | ||||
| 					d := fs.NewDir(f.dirNames.Save(newRemote, f.cleanRemote(newRemote)), fi.ModTime()) | ||||
| 					entries = append(entries, d) | ||||
| 				} | ||||
| 			} else { | ||||
|   | ||||
| @@ -423,14 +423,9 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 		if info.Folder != nil { | ||||
| 			// cache the directory ID for later lookups | ||||
| 			f.dirCache.Put(remote, info.ID) | ||||
| 			d := &fs.Dir{ | ||||
| 				Name:  remote, | ||||
| 				Bytes: -1, | ||||
| 				Count: -1, | ||||
| 				When:  time.Time(info.LastModifiedDateTime), | ||||
| 			} | ||||
| 			d := fs.NewDir(remote, time.Time(info.LastModifiedDateTime)) | ||||
| 			if info.Folder != nil { | ||||
| 				d.Count = info.Folder.ChildCount | ||||
| 				d.SetItems(info.Folder.ChildCount) | ||||
| 			} | ||||
| 			entries = append(entries, d) | ||||
| 		} else { | ||||
|   | ||||
							
								
								
									
										13
									
								
								s3/s3.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								s3/s3.go
									
									
									
									
									
								
							| @@ -555,11 +555,7 @@ func (f *Fs) itemToDirEntry(remote string, object *s3.Object, isDirectory bool) | ||||
| 		if object.Size != nil { | ||||
| 			size = *object.Size | ||||
| 		} | ||||
| 		d := &fs.Dir{ | ||||
| 			Name:  remote, | ||||
| 			Bytes: size, | ||||
| 			Count: 0, | ||||
| 		} | ||||
| 		d := fs.NewDir(remote, time.Time{}).SetSize(size) | ||||
| 		return d, nil | ||||
| 	} | ||||
| 	o, err := f.newObjectWithInfo(remote, object) | ||||
| @@ -599,12 +595,7 @@ func (f *Fs) listBuckets(dir string) (entries fs.DirEntries, err error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, bucket := range resp.Buckets { | ||||
| 		d := &fs.Dir{ | ||||
| 			Name:  aws.StringValue(bucket.Name), | ||||
| 			When:  aws.TimeValue(bucket.CreationDate), | ||||
| 			Bytes: -1, | ||||
| 			Count: -1, | ||||
| 		} | ||||
| 		d := fs.NewDir(aws.StringValue(bucket.Name), aws.TimeValue(bucket.CreationDate)) | ||||
| 		entries = append(entries, d) | ||||
| 	} | ||||
| 	return entries, nil | ||||
|   | ||||
| @@ -264,12 +264,7 @@ func (f *Fs) List(dir string) (entries fs.DirEntries, err error) { | ||||
| 	for _, info := range infos { | ||||
| 		remote := path.Join(dir, info.Name()) | ||||
| 		if info.IsDir() { | ||||
| 			d := &fs.Dir{ | ||||
| 				Name:  remote, | ||||
| 				When:  info.ModTime(), | ||||
| 				Bytes: -1, | ||||
| 				Count: -1, | ||||
| 			} | ||||
| 			d := fs.NewDir(remote, info.ModTime()) | ||||
| 			entries = append(entries, d) | ||||
| 		} else { | ||||
| 			o := &Object{ | ||||
|   | ||||
| @@ -321,11 +321,7 @@ type addEntryFn func(fs.DirEntry) error | ||||
| func (f *Fs) list(dir string, recurse bool, fn addEntryFn) error { | ||||
| 	return f.listContainerRoot(f.container, f.root, dir, recurse, func(remote string, object *swift.Object, isDirectory bool) (err error) { | ||||
| 		if isDirectory { | ||||
| 			d := &fs.Dir{ | ||||
| 				Name:  remote, | ||||
| 				Bytes: object.Bytes, | ||||
| 				Count: 0, | ||||
| 			} | ||||
| 			d := fs.NewDir(remote, time.Time{}).SetSize(object.Bytes) | ||||
| 			err = fn(d) | ||||
| 		} else { | ||||
| 			o, err := f.newObjectWithInfo(remote, object) | ||||
| @@ -370,11 +366,7 @@ func (f *Fs) listContainers(dir string) (entries fs.DirEntries, err error) { | ||||
| 		return nil, errors.Wrap(err, "container listing failed") | ||||
| 	} | ||||
| 	for _, container := range containers { | ||||
| 		d := &fs.Dir{ | ||||
| 			Name:  container.Name, | ||||
| 			Bytes: container.Bytes, | ||||
| 			Count: container.Count, | ||||
| 		} | ||||
| 		d := fs.NewDir(container.Name, time.Time{}).SetSize(container.Bytes).SetItems(container.Count) | ||||
| 		entries = append(entries, d) | ||||
| 	} | ||||
| 	return entries, nil | ||||
|   | ||||
| @@ -174,12 +174,7 @@ func (f *Fs) itemToDirEntry(remote string, object *yandex.ResourceInfoResponse) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrap(err, "error parsing time in directory item") | ||||
| 		} | ||||
| 		d := &fs.Dir{ | ||||
| 			Name:  remote, | ||||
| 			When:  t, | ||||
| 			Bytes: int64(object.Size), | ||||
| 			Count: -1, | ||||
| 		} | ||||
| 		d := fs.NewDir(remote, t).SetSize(int64(object.Size)) | ||||
| 		return d, nil | ||||
| 	case "file": | ||||
| 		o, err := f.newObjectWithInfo(remote, object) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user