-
-
Notifications
You must be signed in to change notification settings - Fork 8k
feat(github_release): add GitHub Release driver #7859
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
vvtommy
wants to merge
8
commits into
AlistGo:main
Choose a base branch
from
vvtommy:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a0aaf0d
feat(github_release): add GitHub Release driver
vvtommy c14fe2f
chore(github_release): enhance help messages for repo, token, and max…
vvtommy b266a31
feat(github_release): add latest release support
vvtommy 7b1dd2f
chore(github_release): adjust backoff parameters for retry logic
vvtommy becff33
refactor(github_release): update API methods to accept context for im…
vvtommy 009a46a
chore(github_release): rename package
vvtommy 39a924d
fix(github_release): correcting a test iteration number
vvtommy 0bce51d
fix(github_release): corect the error logic when the latest release i…
vvtommy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package template | ||
|
|
||
| import ( | ||
| "math/rand" | ||
| "time" | ||
| ) | ||
|
|
||
| const ( | ||
| initialRetryInterval = 500 * time.Millisecond | ||
| maxInterval = 1 * time.Minute | ||
| maxElapsedTime = 15 * time.Minute | ||
| randomizationFactor = 0.5 | ||
| multiplier = 1.5 | ||
| ) | ||
|
|
||
| // Backoff 提供了确定在重试操作之前等待的时间算法 | ||
| type Backoff struct { | ||
| interval time.Duration | ||
| elapsedTime time.Duration | ||
| } | ||
|
|
||
| // Pause 返回重试操作之前等待的时间量,如果可以再次尝试则返回 true,否则返回 false,表示操作应该被放弃。 | ||
| func (b *Backoff) Pause() (time.Duration, bool) { | ||
| if b.interval == 0 { | ||
| // first time | ||
| b.interval = initialRetryInterval | ||
| b.elapsedTime = 0 | ||
| } | ||
|
|
||
| // interval from [1 - randomizationFactor, 1 + randomizationFactor) | ||
| randomizedInterval := time.Duration((rand.Float64()*(2*randomizationFactor) + (1 - randomizationFactor)) * float64(b.interval)) | ||
| b.elapsedTime += randomizedInterval | ||
|
|
||
| if b.elapsedTime > maxElapsedTime { | ||
| return 0, false | ||
| } | ||
|
|
||
| // 将间隔增加到间隔上限 | ||
| b.interval = time.Duration(float64(b.interval) * multiplier) | ||
| if b.interval > maxInterval { | ||
| b.interval = maxInterval | ||
| } | ||
|
|
||
| return randomizedInterval, true | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package template | ||
|
|
||
| import ( | ||
| "testing" | ||
| "time" | ||
| ) | ||
|
|
||
| func TestBackoffMultiple(t *testing.T) { | ||
| b := &Backoff{} | ||
| for i := 0; i < 19; i++ { | ||
| p, ok := b.Pause() | ||
| t.Logf("iteration %d pausing for %s", i, p) | ||
| if !ok { | ||
| t.Fatalf("hit the pause timeout after %d pauses", i) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func TestBackoffTimeout(t *testing.T) { | ||
| var elapsed time.Duration | ||
| b := &Backoff{} | ||
| for i := 0; i < 40; i++ { | ||
| p, ok := b.Pause() | ||
| elapsed += p | ||
| t.Logf("iteration %d pausing for %s (total %s)", i, p, elapsed) | ||
| if !ok { | ||
| break | ||
| } | ||
| } | ||
| if _, ok := b.Pause(); ok { | ||
| t.Fatalf("did not hit the pause timeout") | ||
| } | ||
|
|
||
| if elapsed > maxElapsedTime { | ||
| t.Fatalf("waited too long: %s > %s", elapsed, maxElapsedTime) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| package template | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "net/http" | ||
| "strconv" | ||
| "strings" | ||
|
|
||
| "github.com/alist-org/alist/v3/internal/conf" | ||
| "github.com/alist-org/alist/v3/internal/driver" | ||
| "github.com/alist-org/alist/v3/internal/errs" | ||
| "github.com/alist-org/alist/v3/internal/model" | ||
| "github.com/pkg/errors" | ||
| ) | ||
|
|
||
| type GithubRelease struct { | ||
| model.Storage | ||
| Addition | ||
|
|
||
| api *ApiContext | ||
| repo repository | ||
| } | ||
|
|
||
| func (d *GithubRelease) Config() driver.Config { | ||
| return config | ||
| } | ||
|
|
||
| func (d *GithubRelease) GetAddition() driver.Additional { | ||
| return &d.Addition | ||
| } | ||
|
|
||
| func (d *GithubRelease) Init(ctx context.Context) error { | ||
| token := d.Addition.Token | ||
| if token == "" { | ||
| return errs.EmptyToken | ||
| } | ||
|
|
||
| if d.Addition.MaxReleases < 1 { | ||
| return errors.New("max_releases must be greater than 0") | ||
| } | ||
|
|
||
| if d.Addition.MaxReleases > 100 { | ||
| d.Addition.MaxReleases = 100 | ||
| } | ||
|
|
||
| d.api = NewApiContext(token, nil) | ||
|
|
||
| repo, err := newRepository(d.Addition.Repo) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| d.repo = repo | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| // Drop Delete this driver | ||
| func (d *GithubRelease) Drop(ctx context.Context) error { | ||
| return nil | ||
| } | ||
|
|
||
| func (d *GithubRelease) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { | ||
| repo, err := newRepository(d.Addition.Repo) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // 判断 dir 是不是挂在点。如果 dir 是挂载点,则返回所有的 release; | ||
| // 如果 dir 不是挂载点,则返回 dir 下的 release。 | ||
| if dir.GetPath() == "" { | ||
| releases, err := d.api.GetReleases(repo, d.Addition.MaxReleases) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return releases, nil | ||
| } | ||
|
|
||
| idStr := dir.GetID() | ||
| id, err := strconv.ParseInt(idStr, 10, 64) | ||
| if err != nil { | ||
| return nil, errors.Wrapf(err, "list release %s failed, id is not a number", idStr) | ||
| } | ||
|
|
||
| release, err := d.api.GetRelease(repo, id) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return release.Children() | ||
| } | ||
|
|
||
| func (d *GithubRelease) proxyDownload(file model.Obj, args model.LinkArgs) bool { | ||
| if d.Config().MustProxy() || d.GetStorage().WebProxy { | ||
| return true | ||
| } | ||
|
|
||
| req := args.HttpReq | ||
| if args.HttpReq != nil && | ||
| req.URL != nil && | ||
| strings.HasPrefix(req.URL.Path, fmt.Sprintf("/p%s", d.GetStorage().MountPath)) { | ||
| return true | ||
| } | ||
|
|
||
| return false | ||
| } | ||
|
|
||
| func (d *GithubRelease) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { | ||
| idStr := file.GetID() | ||
| id, err := strconv.ParseInt(idStr, 10, 64) | ||
| if err != nil { | ||
| return nil, errors.Wrapf(err, "get link of file %s failed, id is not a number", idStr) | ||
| } | ||
| asset, err := d.api.GetReleaseAsset(d.repo, id) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| if d.proxyDownload(file, args) { | ||
|
|
||
| header := http.Header{ | ||
| "User-Agent": {"Alist/" + conf.VERSION}, | ||
| "Accept": {"application/octet-stream"}, | ||
| } | ||
| d.api.SetAuthHeader(header) | ||
|
|
||
| return &model.Link{ | ||
| URL: asset.URL, | ||
| Header: header, | ||
| }, nil | ||
| } | ||
|
|
||
| return &model.Link{ | ||
| URL: asset.BrowserDownloadURL, | ||
| }, nil | ||
|
|
||
| } | ||
|
|
||
| func (d *GithubRelease) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) { | ||
| return nil, errs.NotSupport | ||
| } | ||
|
|
||
| func (d *GithubRelease) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) { | ||
| return nil, errs.NotSupport | ||
| } | ||
|
|
||
| func (d *GithubRelease) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) { | ||
| // TODO rename obj, optional | ||
| return nil, errs.NotImplement | ||
| } | ||
|
|
||
| func (d *GithubRelease) Copy(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) { | ||
| return nil, errs.NotSupport | ||
| } | ||
|
|
||
| func (d *GithubRelease) Remove(ctx context.Context, obj model.Obj) error { | ||
| return errs.NotSupport | ||
| } | ||
|
|
||
| func (d *GithubRelease) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) { | ||
| return nil, errs.NotSupport | ||
| } | ||
|
|
||
| //func (d *Template) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) { | ||
| // return nil, errs.NotSupport | ||
| //} | ||
|
|
||
| var _ driver.Driver = (*GithubRelease)(nil) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.