2020-11-18 22:57:17 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"log"
|
|
|
|
"sort"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (this *Application) sync(ctx context.Context) (bool, error) {
|
|
|
|
|
|
|
|
// List repositories on Gitea
|
|
|
|
repos, err := this.repos(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare this list of repositories to our existing one
|
|
|
|
// If the repository is new, or if it's update-time has changed since we last
|
|
|
|
// saw it, then re-refresh its real git commit timestamps
|
|
|
|
// Otherwise copy them from the previous version
|
|
|
|
|
|
|
|
this.reposMut.RLock() // readonly
|
|
|
|
|
|
|
|
anyChanges := false
|
|
|
|
if len(repos) != len(this.reposCache) {
|
|
|
|
anyChanges = true
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, rr := range repos {
|
|
|
|
if idx, ok := this.reposAlphabeticalOrder[rr.Name]; ok && this.reposCache[idx].GiteaUpdated == rr.GiteaUpdated {
|
|
|
|
// Already exists in cache with same Gitea update time
|
|
|
|
// Copy timestamps
|
|
|
|
repos[i] = this.reposCache[idx]
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// New repo, or Gitea has updated timestamp
|
|
|
|
anyChanges = true
|
|
|
|
|
|
|
|
// Refresh timestamps
|
|
|
|
this.populateCommitInfo(ctx, &rr)
|
|
|
|
|
|
|
|
// Refresh topics
|
|
|
|
if t, err := this.topicsForRepo(ctx, rr.Name); err == nil {
|
|
|
|
rr.topics = t
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save
|
|
|
|
repos[i] = rr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.reposMut.RUnlock()
|
|
|
|
|
|
|
|
//
|
|
|
|
if !anyChanges {
|
|
|
|
return false, nil // nothing to do
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have a final updated repos array
|
|
|
|
|
|
|
|
// Sort repos once alphabetically, to get alphabetical indexes...
|
|
|
|
sort.Slice(repos, func(i, j int) bool {
|
|
|
|
return repos[i].Name < repos[j].Name
|
|
|
|
})
|
|
|
|
alphabeticalOrderIndexes := make(map[string]int, len(repos))
|
|
|
|
for idx, repo := range repos {
|
|
|
|
alphabeticalOrderIndexes[repo.Name] = idx
|
|
|
|
}
|
|
|
|
|
|
|
|
// But then make sure the final sort is by most-recently-created
|
|
|
|
sort.Slice(repos, func(i, j int) bool {
|
2020-11-18 23:06:57 +00:00
|
|
|
return repos[i].GiteaCreated.After(repos[j].GiteaCreated)
|
2020-11-18 22:57:17 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// Commit our changes for the other threads to look at
|
|
|
|
this.reposMut.Lock()
|
|
|
|
this.reposCache = repos
|
|
|
|
this.reposAlphabeticalOrder = alphabeticalOrderIndexes
|
|
|
|
this.reposMut.Unlock()
|
|
|
|
|
|
|
|
// Done
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *Application) syncWorker(ctx context.Context) {
|
|
|
|
|
|
|
|
t := time.NewTicker(30 * time.Minute)
|
|
|
|
defer t.Stop()
|
|
|
|
|
|
|
|
for {
|
|
|
|
anyChanges, err := this.sync(ctx)
|
|
|
|
if err != nil {
|
|
|
|
// log and continue
|
|
|
|
log.Printf("Refreshing repositories: %s", err.Error())
|
|
|
|
}
|
|
|
|
if anyChanges {
|
|
|
|
log.Printf("Repositories updated")
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-t.C:
|
|
|
|
continue
|
|
|
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|