@@ -445,18 +445,133 @@ func (g *Gitee) Archive(ctx context.Context, opts *domain.ArchiveOptions) (*doma
445445
446446// Branches 实现 GitPlatformClient 接口
447447func (g * Gitee ) Branches (ctx context.Context , opts * domain.BranchesOptions ) ([]* domain.BranchInfo , error ) {
448- // TODO: 实现 Gitee branches 列表
449- return nil , fmt .Errorf ("not implemented" )
448+ resp , err := ListBranches (ctx , opts .Token , opts .Owner , opts .Repo , opts .Page , opts .PerPage , opts .IsOAuth )
449+ if err != nil {
450+ return nil , err
451+ }
452+ result := make ([]* domain.BranchInfo , 0 , len (resp ))
453+ for _ , b := range resp {
454+ result = append (result , & domain.BranchInfo {Name : b .Name })
455+ }
456+ return result , nil
450457}
451458
452459// DeleteWebhook 实现 GitPlatformClient 接口
453460func (g * Gitee ) DeleteWebhook (ctx context.Context , opts * domain.WebhookOptions ) error {
454- // TODO: 实现 Gitee webhook 删除
455- return fmt .Errorf ("not implemented" )
461+ owner , repo , err := parseGiteeRepoPath (opts .RepoURL )
462+ if err != nil {
463+ return err
464+ }
465+
466+ client := & http.Client {Timeout : 30 * time .Second }
467+
468+ // 分页查找匹配的 webhook
469+ for page := 1 ; ; page ++ {
470+ apiURL := fmt .Sprintf ("https://gitee.com/api/v5/repos/%s/%s/hooks?page=%d&per_page=100" ,
471+ url .PathEscape (owner ), url .PathEscape (repo ), page )
472+ if opts .IsOAuth {
473+ apiURL += "&access_token=" + url .QueryEscape (opts .Token )
474+ }
475+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , apiURL , nil )
476+ if err != nil {
477+ return fmt .Errorf ("create request: %w" , err )
478+ }
479+ if ! opts .IsOAuth {
480+ req .Header .Set ("Authorization" , "token " + opts .Token )
481+ }
482+ resp , err := client .Do (req )
483+ if err != nil {
484+ return fmt .Errorf ("list hooks: %w" , err )
485+ }
486+ body , _ := io .ReadAll (resp .Body )
487+ resp .Body .Close ()
488+ if resp .StatusCode != http .StatusOK {
489+ return fmt .Errorf ("list hooks returned status %d: %s" , resp .StatusCode , string (body ))
490+ }
491+
492+ var hooks []struct {
493+ ID int64 `json:"id"`
494+ URL string `json:"url"`
495+ }
496+ if err := json .Unmarshal (body , & hooks ); err != nil {
497+ return fmt .Errorf ("unmarshal hooks: %w" , err )
498+ }
499+ if len (hooks ) == 0 {
500+ break
501+ }
502+ for _ , hook := range hooks {
503+ if hook .URL == opts .WebhookURL {
504+ deleteURL := fmt .Sprintf ("https://gitee.com/api/v5/repos/%s/%s/hooks/%d" ,
505+ url .PathEscape (owner ), url .PathEscape (repo ), hook .ID )
506+ if opts .IsOAuth {
507+ deleteURL += "?access_token=" + url .QueryEscape (opts .Token )
508+ }
509+ delReq , err := http .NewRequestWithContext (ctx , http .MethodDelete , deleteURL , nil )
510+ if err != nil {
511+ return fmt .Errorf ("create delete request: %w" , err )
512+ }
513+ if ! opts .IsOAuth {
514+ delReq .Header .Set ("Authorization" , "token " + opts .Token )
515+ }
516+ delResp , err := client .Do (delReq )
517+ if err != nil {
518+ return fmt .Errorf ("delete hook %d: %w" , hook .ID , err )
519+ }
520+ delResp .Body .Close ()
521+ if delResp .StatusCode != http .StatusOK && delResp .StatusCode != http .StatusNoContent {
522+ return fmt .Errorf ("delete hook %d returned status %d" , hook .ID , delResp .StatusCode )
523+ }
524+ return nil
525+ }
526+ }
527+ }
528+ return nil
456529}
457530
458531// CreateWebhook 实现 GitPlatformClient 接口
459532func (g * Gitee ) CreateWebhook (ctx context.Context , opts * domain.CreateWebhookOptions ) error {
460- // TODO: 实现 Gitee webhook 创建
461- return fmt .Errorf ("not implemented" )
533+ owner , repo , err := parseGiteeRepoPath (opts .RepoURL )
534+ if err != nil {
535+ return err
536+ }
537+
538+ client := & http.Client {Timeout : 30 * time .Second }
539+ apiURL := fmt .Sprintf ("https://gitee.com/api/v5/repos/%s/%s/hooks" ,
540+ url .PathEscape (owner ), url .PathEscape (repo ))
541+
542+ payload := map [string ]any {
543+ "url" : opts .WebhookURL ,
544+ "password" : opts .SecretToken ,
545+ "push_events" : true ,
546+ "merge_requests_events" : true ,
547+ "note_events" : true ,
548+ }
549+ if opts .IsOAuth {
550+ payload ["access_token" ] = opts .Token
551+ }
552+
553+ jsonBody , err := json .Marshal (payload )
554+ if err != nil {
555+ return fmt .Errorf ("marshal payload: %w" , err )
556+ }
557+
558+ req , err := http .NewRequestWithContext (ctx , http .MethodPost , apiURL , bytes .NewReader (jsonBody ))
559+ if err != nil {
560+ return fmt .Errorf ("create request: %w" , err )
561+ }
562+ req .Header .Set ("Content-Type" , "application/json" )
563+ if ! opts .IsOAuth {
564+ req .Header .Set ("Authorization" , "token " + opts .Token )
565+ }
566+
567+ resp , err := client .Do (req )
568+ if err != nil {
569+ return fmt .Errorf ("create webhook: %w" , err )
570+ }
571+ defer resp .Body .Close ()
572+ if resp .StatusCode != http .StatusCreated && resp .StatusCode != http .StatusOK {
573+ body , _ := io .ReadAll (resp .Body )
574+ return fmt .Errorf ("create webhook returned status %d: %s" , resp .StatusCode , string (body ))
575+ }
576+ return nil
462577}
0 commit comments