googlephotos: fix creation of duplicated albums
Also make sure we don't list the albums twice
This commit is contained in:
parent
d72e4105fb
commit
d7016866e0
1 changed files with 35 additions and 27 deletions
|
@ -150,9 +150,11 @@ type Fs struct {
|
||||||
srv *rest.Client // the connection to the one drive server
|
srv *rest.Client // the connection to the one drive server
|
||||||
pacer *fs.Pacer // To pace the API calls
|
pacer *fs.Pacer // To pace the API calls
|
||||||
startTime time.Time // time Fs was started - used for datestamps
|
startTime time.Time // time Fs was started - used for datestamps
|
||||||
|
albumsMu sync.Mutex // protect albums (but not contents)
|
||||||
albums map[bool]*albums // albums, shared or not
|
albums map[bool]*albums // albums, shared or not
|
||||||
uploadedMu sync.Mutex // to protect the below
|
uploadedMu sync.Mutex // to protect the below
|
||||||
uploaded dirtree.DirTree // record of uploaded items
|
uploaded dirtree.DirTree // record of uploaded items
|
||||||
|
createMu sync.Mutex // held when creating albums to prevent dupes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object describes a storage object
|
// Object describes a storage object
|
||||||
|
@ -334,6 +336,8 @@ func findID(name string) string {
|
||||||
// list the albums into an internal cache
|
// list the albums into an internal cache
|
||||||
// FIXME cache invalidation
|
// FIXME cache invalidation
|
||||||
func (f *Fs) listAlbums(shared bool) (all *albums, err error) {
|
func (f *Fs) listAlbums(shared bool) (all *albums, err error) {
|
||||||
|
f.albumsMu.Lock()
|
||||||
|
defer f.albumsMu.Unlock()
|
||||||
all, ok := f.albums[shared]
|
all, ok := f.albums[shared]
|
||||||
if ok && all != nil {
|
if ok && all != nil {
|
||||||
return all, nil
|
return all, nil
|
||||||
|
@ -532,7 +536,7 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
|
||||||
}
|
}
|
||||||
|
|
||||||
// createAlbum creates the album
|
// createAlbum creates the album
|
||||||
func (f *Fs) createAlbum(ctx context.Context, albumName string) (album *api.Album, err error) {
|
func (f *Fs) createAlbum(ctx context.Context, albumTitle string) (album *api.Album, err error) {
|
||||||
opts := rest.Opts{
|
opts := rest.Opts{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
Path: "/albums",
|
Path: "/albums",
|
||||||
|
@ -540,7 +544,7 @@ func (f *Fs) createAlbum(ctx context.Context, albumName string) (album *api.Albu
|
||||||
}
|
}
|
||||||
var request = api.CreateAlbum{
|
var request = api.CreateAlbum{
|
||||||
Album: &api.Album{
|
Album: &api.Album{
|
||||||
Title: albumName,
|
Title: albumTitle,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var result api.Album
|
var result api.Album
|
||||||
|
@ -556,6 +560,23 @@ func (f *Fs) createAlbum(ctx context.Context, albumName string) (album *api.Albu
|
||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getOrCreateAlbum gets an existing album or creates a new one
|
||||||
|
//
|
||||||
|
// It does the creation with the lock held to avoid duplicates
|
||||||
|
func (f *Fs) getOrCreateAlbum(ctx context.Context, albumTitle string) (album *api.Album, err error) {
|
||||||
|
f.createMu.Lock()
|
||||||
|
defer f.createMu.Unlock()
|
||||||
|
albums, err := f.listAlbums(false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
album, ok := albums.get(albumTitle)
|
||||||
|
if ok {
|
||||||
|
return album, nil
|
||||||
|
}
|
||||||
|
return f.createAlbum(ctx, albumTitle)
|
||||||
|
}
|
||||||
|
|
||||||
// Mkdir creates the album if it doesn't exist
|
// Mkdir creates the album if it doesn't exist
|
||||||
func (f *Fs) Mkdir(ctx context.Context, dir string) (err error) {
|
func (f *Fs) Mkdir(ctx context.Context, dir string) (err error) {
|
||||||
defer log.Trace(f, "dir=%q", dir)("err=%v", &err)
|
defer log.Trace(f, "dir=%q", dir)("err=%v", &err)
|
||||||
|
@ -573,16 +594,8 @@ func (f *Fs) Mkdir(ctx context.Context, dir string) (err error) {
|
||||||
f.uploadedMu.Unlock()
|
f.uploadedMu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
albumName := match[1]
|
albumTitle := match[1]
|
||||||
allAlbums, err := f.listAlbums(false)
|
_, err = f.getOrCreateAlbum(ctx, albumTitle)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, ok := allAlbums.get(albumName)
|
|
||||||
if ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
_, err = f.createAlbum(ctx, albumName)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,12 +619,12 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) (err error) {
|
||||||
f.uploadedMu.Unlock()
|
f.uploadedMu.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
albumName := match[1]
|
albumTitle := match[1]
|
||||||
allAlbums, err := f.listAlbums(false)
|
allAlbums, err := f.listAlbums(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
album, ok := allAlbums.get(albumName)
|
album, ok := allAlbums.get(albumTitle)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fs.ErrorDirNotFound
|
return fs.ErrorDirNotFound
|
||||||
}
|
}
|
||||||
|
@ -825,19 +838,14 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
|
||||||
if pattern.isUpload {
|
if pattern.isUpload {
|
||||||
fileName = match[1]
|
fileName = match[1]
|
||||||
} else {
|
} else {
|
||||||
var albumName string
|
var albumTitle string
|
||||||
albumName, fileName = match[1], match[2]
|
albumTitle, fileName = match[1], match[2]
|
||||||
|
|
||||||
// Create album if not found
|
album, err := o.fs.getOrCreateAlbum(ctx, albumTitle)
|
||||||
album, ok := o.fs.albums[false].get(albumName)
|
if err != nil {
|
||||||
if !ok {
|
return err
|
||||||
album, err = o.fs.createAlbum(ctx, albumName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check we can write to this album
|
|
||||||
if !album.IsWriteable {
|
if !album.IsWriteable {
|
||||||
return errOwnAlbums
|
return errOwnAlbums
|
||||||
}
|
}
|
||||||
|
@ -919,10 +927,10 @@ func (o *Object) Remove(ctx context.Context) (err error) {
|
||||||
if pattern == nil || !pattern.isFile || !pattern.canUpload || pattern.isUpload {
|
if pattern == nil || !pattern.isFile || !pattern.canUpload || pattern.isUpload {
|
||||||
return errRemove
|
return errRemove
|
||||||
}
|
}
|
||||||
albumName, fileName := match[1], match[2]
|
albumTitle, fileName := match[1], match[2]
|
||||||
album, ok := o.fs.albums[false].get(albumName)
|
album, ok := o.fs.albums[false].get(albumTitle)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Errorf("couldn't file %q in album %q for delete", fileName, albumName)
|
return errors.Errorf("couldn't file %q in album %q for delete", fileName, albumTitle)
|
||||||
}
|
}
|
||||||
opts := rest.Opts{
|
opts := rest.Opts{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
|
|
Loading…
Reference in a new issue