ronantakizawa/codereview-bench huggingface dataset:
Repository: go-gitea/gitea
File: routers/api/v1/repo/issue.go (Go)

Code before:
	//   minimum: 1
	//   default: 1
	// - name: limit
	//   in: query
	//   description: Number of items per page
	//   type: integer
	//   minimum: 0
	// responses:
	//   "200":
	//     "$ref": "#/responses/IssueList"
	//   "400":
	//     "$ref": "#/responses/error"
	//   "422":
	//     "$ref": "#/responses/validationError"

	before, since, err := context.GetQueryBeforeSince(ctx.Base)
	if err != nil {
		ctx.APIError(http.StatusUnprocessableEntity, err)
		return
	}

	isClosed := parseIssueIsClosed(ctx)

	repoIDs, allPublic, err := buildSearchIssuesRepoIDs(ctx)
	if err != nil {
		if user_model.IsErrUserNotExist(err) || organization.IsErrTeamNotExist(err) || err.Error() == "owner organisation is required for filtering on team" {
			ctx.APIError(http.StatusBadRequest, err)
		} else {
			ctx.APIErrorInternal(err)
		}
		return
	}

	keyword := ctx.FormTrim("q")
	if strings.IndexByte(keyword, 0) >= 0 {
		keyword = ""
	}

	isPull := parseIssueIsPull(ctx)

	var includedAnyLabels []int64
	{
		labels := ctx.FormTrim("labels")
		var includedLabelNames []string
		if len(labels) > 0 {
			includedLabelNames = strings.Split(labels, ",")
		}
		includedAnyLabels, err = issues_model.GetLabelIDsByNames(ctx, includedLabelNames)
		if err != nil {
			ctx.APIErrorInternal(err)
			return

Review comment (suggestion):
` err.Error() == "owner organisation is required for filtering on team" `

please don't do this, it is an abuse to Golang error system and is very fragile.

Code after:
	}

	keyword := ctx.FormTrim("q")
	if strings.IndexByte(keyword, 0) >= 0 {
		keyword = ""
	}

	isPull := common.ParseIssueFilterTypeIsPull(ctx.FormString("type"))

	var includedAnyLabels []int64
	{
		labels := ctx.FormTrim("labels")
		var includedLabelNames []string
		if len(labels) > 0 {
			includedLabelNames = strings.Split(labels, ",")
		}
		includedAnyLabels, err = issues_model.GetLabelIDsByNames(ctx, includedLabelNames)
		if err != nil {
			ctx.APIErrorInternal(err)
			return
		}
	}

	var includedMilestones []int64
	{
		milestones := ctx.FormTrim("milestones")
		var includedMilestoneNames []string
		if len(milestones) > 0 {
			includedMilestoneNames = strings.Split(milestones, ",")
		}
		includedMilestones, err = issues_model.GetMilestoneIDsByNames(ctx, includedMilestoneNames)
		if err != nil {
			ctx.APIErrorInternal(err)
			return
		}
	}

	limit := util.IfZero(ctx.FormInt("limit"), setting.API.DefaultPagingNum)

	searchOpt := &issue_indexer.SearchOptions{
		Paginator: &db.ListOptions{
			PageSize: limit,
			Page:     ctx.FormInt("page"),
		},
		Keyword:             keyword,
		RepoIDs:             repoIDs,
		AllPublic:           allPublic,
		IsPull:              isPull,
		IsClosed:            isClosed,
		IncludedAnyLabelIDs: includedAnyLabels,
		MilestoneIDs:        includedMilestones,
Repository: go-gitea/gitea
File: web_src/js/modules/user-settings.ts (TypeScript)

Code before:

function setLocalStorageUserSetting(settingKey: string, value: string) {
  const legacyKey = settingKey;
  const itemKey = `${itemKeyPrefix}${settingKey}`;
  try {
    localStorage?.removeItem(legacyKey);
    localStorage?.setItem(itemKey, value);
  } catch (e) {
    handleLocalStorageError(e);
  }
}

export const localUserSettings = {
  getString: (key: string, def: string = ''): string => {
    return getLocalStorageUserSetting(key) ?? def;
  },
  setString: (key: string, value: string) => {
    setLocalStorageUserSetting(key, value);
  },
  getBoolean: (key: string, def: boolean = false): boolean => {
    return localUserSettings.getString(key, String(def)) === 'true';
  },
  setBoolean: (key: string, value: boolean) => {
    localUserSettings.setString(key, String(value));
  },
  getJsonObject: (key: string, def: any = null): any => {
    try {
      const value = getLocalStorageUserSetting(key);
      return value !== null ? JSON.parse(value) : def;
    } catch {}
    return def;
  },
  setJsonObject: (key: string, value: any) => {
    localUserSettings.setString(key, JSON.stringify(value));
  },
};

window.localUserSettings = localUserSettings;


Review comment (suggestion):
```ts
getJsonObject: <T = Record<string, any>>(key: string, def: T = null): T => {
```

And call like

```ts
localUserSettings.getJsonObject<LocaleStorageOptions>('actions-view-options', defaultViewOptions);
```

Code after:
  }
  return null;
}

function setLocalStorageUserSetting(settingKey: string, value: string) {
  const legacyKey = settingKey;
  const itemKey = `${itemKeyPrefix}${settingKey}`;
  try {
    localStorage?.removeItem(legacyKey);
    localStorage?.setItem(itemKey, value);
  } catch (e) {
    handleLocalStorageError(e);
  }
}

export const localUserSettings = {
  getString: (key: string, def: string = ''): string => {
    return getLocalStorageUserSetting(key) ?? def;
  },
  setString: (key: string, value: string) => {
    setLocalStorageUserSetting(key, value);
  },
  getBoolean: (key: string, def: boolean = false): boolean => {
    return localUserSettings.getString(key, String(def)) === 'true';
  },
  setBoolean: (key: string, value: boolean) => {
    localUserSettings.setString(key, String(value));
  },
  getJsonObject: <T extends Record<string, any>>(key: string, def: T): T => {
    const value = getLocalStorageUserSetting(key);
    try {
      const decoded = value !== null ? JSON.parse(value) : def;
      return decoded ?? def;
    } catch (e) {
      console.error(`Unable to parse JSON value for local user settings ${key}=${value}`, e);
    }
    return def;
  },
  setJsonObject: <T extends Record<string, any>>(key: string, value: T) => {
    localUserSettings.setString(key, JSON.stringify(value));
  },
};

window.localUserSettings = localUserSettings;
Repository: go-gitea/gitea
File: web_src/js/modules/user-settings.ts (TypeScript)

Code before:

function setLocalStorageUserSetting(settingKey: string, value: string) {
  const legacyKey = settingKey;
  const itemKey = `${itemKeyPrefix}${settingKey}`;
  try {
    localStorage?.removeItem(legacyKey);
    localStorage?.setItem(itemKey, value);
  } catch (e) {
    handleLocalStorageError(e);
  }
}

export const localUserSettings = {
  getString: (key: string, def: string = ''): string => {
    return getLocalStorageUserSetting(key) ?? def;
  },
  setString: (key: string, value: string) => {
    setLocalStorageUserSetting(key, value);
  },
  getBoolean: (key: string, def: boolean = false): boolean => {
    return localUserSettings.getString(key, String(def)) === 'true';
  },
  setBoolean: (key: string, value: boolean) => {
    localUserSettings.setString(key, String(value));
  },
  getJsonObject: <T extends Record<string, any> | null>(key: string, def: T = (null as T)): T => {
    try {
      const value = getLocalStorageUserSetting(key);
      return value !== null ? JSON.parse(value) : def;
    } catch {}
    return def;
  },
  setJsonObject: (key: string, value: any) => {
    localUserSettings.setString(key, JSON.stringify(value));
  },
};

window.localUserSettings = localUserSettings;


Review comment (suggestion):
It seem not strict.

`getJsonObject` declares that it only returns non-null T, but it can return null.

Code after:
  }
  return null;
}

function setLocalStorageUserSetting(settingKey: string, value: string) {
  const legacyKey = settingKey;
  const itemKey = `${itemKeyPrefix}${settingKey}`;
  try {
    localStorage?.removeItem(legacyKey);
    localStorage?.setItem(itemKey, value);
  } catch (e) {
    handleLocalStorageError(e);
  }
}

export const localUserSettings = {
  getString: (key: string, def: string = ''): string => {
    return getLocalStorageUserSetting(key) ?? def;
  },
  setString: (key: string, value: string) => {
    setLocalStorageUserSetting(key, value);
  },
  getBoolean: (key: string, def: boolean = false): boolean => {
    return localUserSettings.getString(key, String(def)) === 'true';
  },
  setBoolean: (key: string, value: boolean) => {
    localUserSettings.setString(key, String(value));
  },
  getJsonObject: <T extends Record<string, any>>(key: string, def: T): T => {
    const value = getLocalStorageUserSetting(key);
    try {
      const decoded = value !== null ? JSON.parse(value) : def;
      return decoded ?? def;
    } catch (e) {
      console.error(`Unable to parse JSON value for local user settings ${key}=${value}`, e);
    }
    return def;
  },
  setJsonObject: <T extends Record<string, any>>(key: string, value: T) => {
    localUserSettings.setString(key, JSON.stringify(value));
  },
};

window.localUserSettings = localUserSettings;
Repository: go-gitea/gitea
File: services/issue/pull.go (Go)

Code before:

	commit, err := repo.GetBranchCommit(pr.BaseRepo.DefaultBranch)
	if err != nil {
		return nil, err
	}

	var data string
	for _, file := range codeOwnerFiles {
		if blob, err := commit.GetBlobByPath(file); err == nil {
			data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize)
			if err == nil {
				break
			}
		}
	}
	if data == "" {
		return nil, nil
	}

	rules, _ := issues_model.GetCodeOwnersFromContent(ctx, data)
	if len(rules) == 0 {
		return nil, nil
	}

	// get the mergebase
	if pr.MergeBase == "" {
		mergeBase, err := gitrepo.MergeBase(ctx, pr.BaseRepo, git.BranchPrefix+pr.BaseBranch, pr.GetGitHeadRefName())
		if err != nil {
			return nil, err
		}
		pr.MergeBase = mergeBase
	}
	// https://github.com/go-gitea/gitea/issues/29763, we need to get the files changed
	// between the merge base and the head commit but not the base branch and the head commit
	changedFiles, err := repo.GetFilesChangedBetween(pr.MergeBase, pr.GetGitHeadRefName())
	if err != nil {
		return nil, err
	}

	uniqUsers := make(map[int64]*user_model.User)
	uniqTeams := make(map[string]*org_model.Team)
	for _, rule := range rules {
		for _, f := range changedFiles {
			if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) {
				for _, u := range rule.Users {
					uniqUsers[u.ID] = u
				}
				for _, t := range rule.Teams {
					uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t
				}
			}

Review comment (suggestion):
Is it safe to use `MergeBase` here? It can be out-dated because `AddTestPullRequestTask` is executed in a go-routine.

Code after:

	commit, err := repo.GetBranchCommit(pr.BaseRepo.DefaultBranch)
	if err != nil {
		return nil, err
	}

	var data string
	for _, file := range codeOwnerFiles {
		if blob, err := commit.GetBlobByPath(file); err == nil {
			data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize)
			if err == nil {
				break
			}
		}
	}
	if data == "" {
		return nil, nil
	}

	rules, _ := issues_model.GetCodeOwnersFromContent(ctx, data)
	if len(rules) == 0 {
		return nil, nil
	}

	// get the mergebase
	mergeBase, err := gitrepo.MergeBase(ctx, pr.BaseRepo, git.BranchPrefix+pr.BaseBranch, pr.GetGitHeadRefName())
	if err != nil {
		return nil, err
	}
	// https://github.com/go-gitea/gitea/issues/29763, we need to get the files changed
	// between the merge base and the head commit but not the base branch and the head commit
	changedFiles, err := repo.GetFilesChangedBetween(mergeBase, pr.GetGitHeadRefName())
	if err != nil {
		return nil, err
	}

	uniqUsers := make(map[int64]*user_model.User)
	uniqTeams := make(map[string]*org_model.Team)
	for _, rule := range rules {
		for _, f := range changedFiles {
			if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) {
				for _, u := range rule.Users {
					uniqUsers[u.ID] = u
				}
				for _, t := range rule.Teams {
					uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t
				}
			}
		}
	}
Repository: go-gitea/gitea
File: web_src/js/features/user-auth-webauthn.ts (TypeScript)

Code before:
  } else if (res.status !== 201) {
    webAuthnError('unknown');
    return;
  }

  window.location.reload();
}

function webAuthnError(errorType: string, message:string = '') {
  const elErrorMsg = document.querySelector(`#webauthn-error-msg`)!;

  if (errorType === 'general') {
    elErrorMsg.textContent = message || 'unknown error';
  } else {
    const elTypedError = document.querySelector(`#webauthn-error [data-webauthn-error-msg=${errorType}]`);
    if (elTypedError) {
      elErrorMsg.textContent = `${elTypedError.textContent}${message ? ` ${message}` : ''}`;
    } else {
      elErrorMsg.textContent = `unknown error type: ${errorType}${message ? ` ${message}` : ''}`;
    }
  }

  showElem('#webauthn-error');
}

/** Returns the error type or the empty string when there was no error. */
function detectWebAuthnSupport(): string {
  if (!window.isSecureContext) {
    return 'insecure';
  }

  if (typeof window.PublicKeyCredential !== 'function') {
    return 'browser';
  }

  return '';
}

export function initUserAuthWebAuthnRegister() {
  const elRegister = document.querySelector<HTMLInputElement>('#register-webauthn');
  if (!elRegister) return;

  const errorType = detectWebAuthnSupport();
  if (errorType) {
    webAuthnError(errorType);
    elRegister.disabled = true;
    return;
  }
  elRegister.addEventListener('click', async (e) => {
    e.preventDefault();
    await webAuthnRegisterRequest();

Review comment (security):
```suggestion
/**
  * Returns the error type or the empty string when there was no error.
  * The return value is one of the possible values for the `data-webauthn-error-msg` attribute on the webauthn error message element 
  */
```

Code after:
  if (res.status === 409) {
    webAuthnError('duplicated');
    return;
  } else if (res.status !== 201) {
    webAuthnError('unknown');
    return;
  }

  window.location.reload();
}

function webAuthnError(errorType: ErrorType, message:string = '') {
  const elErrorMsg = document.querySelector(`#webauthn-error-msg`)!;

  if (errorType === 'general') {
    elErrorMsg.textContent = message || 'unknown error';
  } else {
    const elTypedError = document.querySelector(`#webauthn-error [data-webauthn-error-msg=${errorType}]`);
    if (elTypedError) {
      elErrorMsg.textContent = `${elTypedError.textContent}${message ? ` ${message}` : ''}`;
    } else {
      elErrorMsg.textContent = `unknown error type: ${errorType}${message ? ` ${message}` : ''}`;
    }
  }

  showElem('#webauthn-error');
}

/** Returns the error type or `null` when there was no error. */
function detectWebAuthnSupport(): ErrorType | null {
  if (!window.isSecureContext) {
    return 'insecure';
  }

  if (typeof window.PublicKeyCredential !== 'function') {
    return 'browser';
  }

  return null;
}

export function initUserAuthWebAuthnRegister() {
  const elRegister = document.querySelector<HTMLInputElement>('#register-webauthn');
  if (!elRegister) return;

  const errorType = detectWebAuthnSupport();
  if (errorType) {
    webAuthnError(errorType);
    elRegister.disabled = true;
    return;
  }
Repository: go-gitea/gitea
File: services/packages/debian/repository.go (Go)

Code before:
	pub, err := user_model.GetSetting(ctx, ownerID, debian_module.SettingKeyPublic)
	if err != nil && !errors.Is(err, util.ErrNotExist) {
		return "", "", err
	}

	if priv == "" || pub == "" {
		priv, pub, err = generateKeypair()
		if err != nil {
			return "", "", err
		}

		if err := user_model.SetUserSetting(ctx, ownerID, debian_module.SettingKeyPrivate, priv); err != nil {
			return "", "", err
		}

		if err := user_model.SetUserSetting(ctx, ownerID, debian_module.SettingKeyPublic, pub); err != nil {
			return "", "", err
		}
	}

	return priv, pub, nil
}

func generateKeypair() (string, string, error) {
	cfg := &packet.Config{
		RSABits:       4096,
		DefaultHash:   crypto.SHA256,
		DefaultCipher: packet.CipherAES256,
	}

	e, err := openpgp.NewEntity("", "Automatically generated Debian Registry Key; created "+time.Now().UTC().Format(time.RFC3339), "", cfg)
	if err != nil {
		return "", "", err
	}

	var priv strings.Builder
	var pub strings.Builder

	w, err := armor.Encode(&priv, openpgp.PrivateKeyType, nil)
	if err != nil {
		return "", "", err
	}
	if err := e.SerializePrivate(w, nil); err != nil {
		return "", "", err
	}
	w.Close()

	w, err = armor.Encode(&pub, openpgp.PublicKeyType, nil)
	if err != nil {
		return "", "", err
	}

Review comment (suggestion):
```suggestion
	// Repository signing keys are long-lived and there is currently no rotation mechanism, choose stronger algorithms
	cfg := &packet.Config{
```

Code after:
	pub, err := user_model.GetSetting(ctx, ownerID, debian_module.SettingKeyPublic)
	if err != nil && !errors.Is(err, util.ErrNotExist) {
		return "", "", err
	}

	if priv == "" || pub == "" {
		priv, pub, err = generateKeypair()
		if err != nil {
			return "", "", err
		}

		if err := user_model.SetUserSetting(ctx, ownerID, debian_module.SettingKeyPrivate, priv); err != nil {
			return "", "", err
		}

		if err := user_model.SetUserSetting(ctx, ownerID, debian_module.SettingKeyPublic, pub); err != nil {
			return "", "", err
		}
	}

	return priv, pub, nil
}

func generateKeypair() (string, string, error) {
	// Repository signing keys are long-lived and there is currently no rotation mechanism, choose stronger algorithms
	cfg := &packet.Config{
		RSABits:       4096,
		DefaultHash:   crypto.SHA256,
		DefaultCipher: packet.CipherAES256,
	}

	e, err := openpgp.NewEntity("", "Automatically generated Debian Registry Key; created "+time.Now().UTC().Format(time.RFC3339), "", cfg)
	if err != nil {
		return "", "", err
	}

	var priv strings.Builder
	var pub strings.Builder

	w, err := armor.Encode(&priv, openpgp.PrivateKeyType, nil)
	if err != nil {
		return "", "", err
	}
	if err := e.SerializePrivate(w, nil); err != nil {
		return "", "", err
	}
	w.Close()

	w, err = armor.Encode(&pub, openpgp.PublicKeyType, nil)
	if err != nil {
		return "", "", err
Repository: go-gitea/gitea
File: routers/web/repo/attachment.go (Go)

Code before:
}

// DeleteAttachment response for deleting issue's attachment
func DeleteAttachment(ctx *context.Context) {
	file := ctx.FormString("file")
	attach, err := repo_model.GetAttachmentByUUID(ctx, file)
	if err != nil {
		ctx.HTTPError(http.StatusBadRequest, err.Error())
		return
	}

	if !ctx.IsSigned {
		ctx.HTTPError(http.StatusForbidden)
		return
	}

	if attach.RepoID != ctx.Repo.Repository.ID {
		ctx.HTTPError(http.StatusBadRequest, "attachment does not belong to this repository")
		return
	}

	if ctx.Doer.ID != attach.UploaderID {
		if attach.IssueID > 0 {
			issue, err := issues_model.GetIssueByID(ctx, attach.IssueID)
			if err != nil {
				ctx.HTTPError(http.StatusInternalServerError, fmt.Sprintf("GetIssueByID: %v", err))
				return
			}
			if !ctx.Repo.Permission.CanWriteIssuesOrPulls(issue.IsPull) {
				ctx.HTTPError(http.StatusForbidden)
				return
			}
		} else if attach.ReleaseID > 0 {
			if !ctx.Repo.Permission.CanWrite(unit.TypeReleases) {
				ctx.HTTPError(http.StatusForbidden)
				return
			}
		} else {
			if !ctx.Repo.Permission.IsAdmin() && !ctx.Repo.Permission.IsOwner() {
				ctx.HTTPError(http.StatusForbidden)
				return
			}
		}
	}

	err = repo_model.DeleteAttachment(ctx, attach, true)
	if err != nil {
		ctx.HTTPError(http.StatusInternalServerError, fmt.Sprintf("DeleteAttachment: %v", err))
		return
	}
	ctx.JSON(http.StatusOK, map[string]string{

Review comment (suggestion):
I think I have told you many many many times: don't expose internal "err" to end users directly. You need to call the framework function to handle internal error and log it.

Code after:

// DeleteAttachment response for deleting issue's attachment
func DeleteAttachment(ctx *context.Context) {
	file := ctx.FormString("file")
	attach, err := repo_model.GetAttachmentByUUID(ctx, file)
	if err != nil {
		ctx.HTTPError(http.StatusBadRequest, err.Error())
		return
	}

	if !ctx.IsSigned {
		ctx.HTTPError(http.StatusForbidden)
		return
	}

	if attach.RepoID != ctx.Repo.Repository.ID {
		ctx.HTTPError(http.StatusBadRequest, "attachment does not belong to this repository")
		return
	}

	if ctx.Doer.ID != attach.UploaderID {
		if attach.IssueID > 0 {
			issue, err := issues_model.GetIssueByID(ctx, attach.IssueID)
			if err != nil {
				ctx.ServerError("GetIssueByID", err)
				return
			}
			if !ctx.Repo.Permission.CanWriteIssuesOrPulls(issue.IsPull) {
				ctx.HTTPError(http.StatusForbidden)
				return
			}
		} else if attach.ReleaseID > 0 {
			if !ctx.Repo.Permission.CanWrite(unit.TypeReleases) {
				ctx.HTTPError(http.StatusForbidden)
				return
			}
		} else {
			if !ctx.Repo.Permission.IsAdmin() && !ctx.Repo.Permission.IsOwner() {
				ctx.HTTPError(http.StatusForbidden)
				return
			}
		}
	}

	err = repo_model.DeleteAttachment(ctx, attach, true)
	if err != nil {
		ctx.ServerError("DeleteAttachment", err)
		return
	}
	ctx.JSON(http.StatusOK, map[string]string{
		"uuid": attach.UUID,
Repository: go-gitea/gitea
File: routers/api/v1/repo/file.go (Go)

Code before:
	// - name: repo
	//   in: path
	//   description: name of the repo
	//   type: string
	//   required: true
	// - name: archive
	//   in: path
	//   description: the git reference for download with attached archive format (e.g. master.zip)
	//   type: string
	//   required: true
	// - name: paths
	//   in: query
	//   type: array
	//   items:
	//     type: string
	//   description: subpath of the repository to download
	// responses:
	//   200:
	//     description: success
	//   "404":
	//     "$ref": "#/responses/notFound"
	var paths []string
	if ctx.FormString("paths") != "" {
		paths = strings.Split(ctx.FormString("paths"), ",")
	}
	serveRepoArchive(ctx, ctx.PathParam("*"), paths)
}

// GetEditorconfig get editor config of a repository
func GetEditorconfig(ctx *context.APIContext) {
	// swagger:operation GET /repos/{owner}/{repo}/editorconfig/{filepath} repository repoGetEditorConfig
	// ---
	// summary: Get the EditorConfig definitions of a file in a repository
	// produces:
	// - application/json
	// parameters:
	// - name: owner
	//   in: path
	//   description: owner of the repo
	//   type: string
	//   required: true
	// - name: repo
	//   in: path
	//   description: name of the repo
	//   type: string
	//   required: true
	// - name: filepath
	//   in: path
	//   description: filepath of file to get
	//   type: string
	//   required: true

Review comment (refactor):
What if there is a comma in a path ....

I think we can use the HTTP query parameter's feature: duplicate key: `/foo?k=1&k=2&k=3`

Code after:
	// - name: repo
	//   in: path
	//   description: name of the repo
	//   type: string
	//   required: true
	// - name: archive
	//   in: path
	//   description: the git reference for download with attached archive format (e.g. master.zip)
	//   type: string
	//   required: true
	// - name: path
	//   in: query
	//   type: array
	//   items:
	//     type: string
	//   description: subpath of the repository to download
	//   collectionFormat: multi
	// responses:
	//   200:
	//     description: success
	//   "404":
	//     "$ref": "#/responses/notFound"
	serveRepoArchive(ctx, ctx.PathParam("*"), ctx.FormStrings("path"))
}

// GetEditorconfig get editor config of a repository
func GetEditorconfig(ctx *context.APIContext) {
	// swagger:operation GET /repos/{owner}/{repo}/editorconfig/{filepath} repository repoGetEditorConfig
	// ---
	// summary: Get the EditorConfig definitions of a file in a repository
	// produces:
	// - application/json
	// parameters:
	// - name: owner
	//   in: path
	//   description: owner of the repo
	//   type: string
	//   required: true
	// - name: repo
	//   in: path
	//   description: name of the repo
	//   type: string
	//   required: true
	// - name: filepath
	//   in: path
	//   description: filepath of file to get
	//   type: string
	//   required: true
	// - name: ref
	//   in: query
	//   description: "The name of the commit/branch/tag. Default to the repository’s default branch."