// Copyright 2016 The Gogs Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo import ( "errors" "fmt" "net/http" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/organization" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" ) // GetBranch get a branch of a repository func GetBranch(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/branches/{branch} repository repoGetBranch // --- // summary: Retrieve a specific branch from a repository, including its effective branch protection // 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: branch // in: path // description: branch to get // type: string // required: true // responses: // "200": // "$ref": "#/responses/Branch" // "404": // "$ref": "#/responses/notFound" branchName := ctx.Params("*") branch, err := ctx.Repo.GitRepo.GetBranch(branchName) if err != nil { if git.IsErrBranchNotExist(err) { ctx.NotFound(err) } else { ctx.Error(http.StatusInternalServerError, "GetBranch", err) } return } c, err := branch.GetCommit() if err != nil { ctx.Error(http.StatusInternalServerError, "GetCommit", err) return } branchProtection, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, branchName) if err != nil { ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err) return } br, err := convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) if err != nil { ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err) return } ctx.JSON(http.StatusOK, br) } // DeleteBranch get a branch of a repository func DeleteBranch(ctx *context.APIContext) { // swagger:operation DELETE /repos/{owner}/{repo}/branches/{branch} repository repoDeleteBranch // --- // summary: Delete a specific branch from 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: branch // in: path // description: branch to delete // type: string // required: true // responses: // "204": // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/error" // "404": // "$ref": "#/responses/notFound" branchName := ctx.Params("*") if err := repo_service.DeleteBranch(ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil { switch { case git.IsErrBranchNotExist(err): ctx.NotFound(err) case errors.Is(err, repo_service.ErrBranchIsDefault): ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch")) case errors.Is(err, repo_service.ErrBranchIsProtected): ctx.Error(http.StatusForbidden, "IsProtectedBranch", fmt.Errorf("branch protected")) default: ctx.Error(http.StatusInternalServerError, "DeleteBranch", err) } return } ctx.Status(http.StatusNoContent) } // CreateBranch creates a branch for a user's repository func CreateBranch(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/branches repository repoCreateBranch // --- // summary: Create a branch // consumes: // - application/json // 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: body // in: body // schema: // "$ref": "#/definitions/CreateBranchRepoOption" // responses: // "201": // "$ref": "#/responses/Branch" // "404": // description: The old branch does not exist. // "409": // description: The branch with the same name already exists. opt := web.GetForm(ctx).(*api.CreateBranchRepoOption) if ctx.Repo.Repository.IsEmpty { ctx.Error(http.StatusNotFound, "", "Git Repository is empty.") return } if len(opt.OldBranchName) == 0 { opt.OldBranchName = ctx.Repo.Repository.DefaultBranch } err := repo_service.CreateNewBranch(ctx, ctx.Doer, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName) if err != nil { if models.IsErrBranchDoesNotExist(err) { ctx.Error(http.StatusNotFound, "", "The old branch does not exist") } if models.IsErrTagAlreadyExists(err) { ctx.Error(http.StatusConflict, "", "The branch with the same tag already exists.") } else if models.IsErrBranchAlreadyExists(err) || git.IsErrPushOutOfDate(err) { ctx.Error(http.StatusConflict, "", "The branch already exists.") } else if models.IsErrBranchNameConflict(err) { ctx.Error(http.StatusConflict, "", "The branch with the same name already exists.") } else { ctx.Error(http.StatusInternalServerError, "CreateRepoBranch", err) } return } branch, err := ctx.Repo.GitRepo.GetBranch(opt.BranchName) if err != nil { ctx.Error(http.StatusInternalServerError, "GetBranch", err) return } commit, err := branch.GetCommit() if err != nil { ctx.Error(http.StatusInternalServerError, "GetCommit", err) return } branchProtection, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, branch.Name) if err != nil { ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err) return } br, err := convert.ToBranch(ctx.Repo.Repository, branch, commit, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) if err != nil { ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err) return } ctx.JSON(http.StatusCreated, br) } // ListBranches list all the branches of a repository func ListBranches(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/branches repository repoListBranches // --- // summary: List a repository's branches // 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: page // in: query // description: page number of results to return (1-based) // type: integer // - name: limit // in: query // description: page size of results // type: integer // responses: // "200": // "$ref": "#/responses/BranchList" listOptions := utils.GetListOptions(ctx) skip, _ := listOptions.GetStartEnd() branches, totalNumOfBranches, err := ctx.Repo.GitRepo.GetBranches(skip, listOptions.PageSize) if err != nil { ctx.Error(http.StatusInternalServerError, "GetBranches", err) return } apiBranches := make([]*api.Branch, len(branches)) for i := range branches { c, err := branches[i].GetCommit() if err != nil { ctx.Error(http.StatusInternalServerError, "GetCommit", err) return } branchProtection, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, branches[i].Name) if err != nil { ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err) return } apiBranches[i], err = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) if err != nil { ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err) return } } ctx.SetLinkHeader(totalNumOfBranches, listOptions.PageSize) ctx.SetTotalCountHeader(int64(totalNumOfBranches)) ctx.JSON(http.StatusOK, &apiBranches) } // GetBranchProtection gets a branch protection func GetBranchProtection(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection // --- // summary: Get a specific branch protection for the 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: name // in: path // description: name of protected branch // type: string // required: true // responses: // "200": // "$ref": "#/responses/BranchProtection" // "404": // "$ref": "#/responses/notFound" repo := ctx.Repo.Repository bpName := ctx.Params(":name") bp, err := models.GetProtectedBranchBy(repo.ID, bpName) if err != nil { ctx.Error(http.StatusInternalServerError, "GetProtectedBranchByID", err) return } if bp == nil || bp.RepoID != repo.ID { ctx.NotFound() return } ctx.JSON(http.StatusOK, convert.ToBranchProtection(bp)) } // ListBranchProtections list branch protections for a repo func ListBranchProtections(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/branch_protections repository repoListBranchProtection // --- // summary: List branch protections for 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 // responses: // "200": // "$ref": "#/responses/BranchProtectionList" repo := ctx.Repo.Repository bps, err := models.GetProtectedBranches(repo.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "GetProtectedBranches", err) return } apiBps := make([]*api.BranchProtection, len(bps)) for i := range bps { apiBps[i] = convert.ToBranchProtection(bps[i]) } ctx.JSON(http.StatusOK, apiBps) } // CreateBranchProtection creates a branch protection for a repo func CreateBranchProtection(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/branch_protections repository repoCreateBranchProtection // --- // summary: Create a branch protections for a repository // consumes: // - application/json // 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: body // in: body // schema: // "$ref": "#/definitions/CreateBranchProtectionOption" // responses: // "201": // "$ref": "#/responses/BranchProtection" // "403": // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" // "422": // "$ref": "#/responses/validationError" form := web.GetForm(ctx).(*api.CreateBranchProtectionOption) repo := ctx.Repo.Repository // Currently protection must match an actual branch if !git.IsBranchExist(ctx.Req.Context(), ctx.Repo.Repository.RepoPath(), form.BranchName) { ctx.NotFound() return } protectBranch, err := models.GetProtectedBranchBy(repo.ID, form.BranchName) if err != nil { ctx.Error(http.StatusInternalServerError, "GetProtectBranchOfRepoByName", err) return } else if protectBranch != nil { ctx.Error(http.StatusForbidden, "Create branch protection", "Branch protection already exist") return } var requiredApprovals int64 if form.RequiredApprovals > 0 { requiredApprovals = form.RequiredApprovals } whitelistUsers, err := user_model.GetUserIDsByNames(form.PushWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) return } ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err) return } mergeWhitelistUsers, err := user_model.GetUserIDsByNames(form.MergeWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) return } ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err) return } approvalsWhitelistUsers, err := user_model.GetUserIDsByNames(form.ApprovalsWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) return } ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err) return } var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64 if repo.Owner.IsOrganization() { whitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) return } ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err) return } mergeWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) return } ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err) return } approvalsWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) return } ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err) return } } protectBranch = &models.ProtectedBranch{ RepoID: ctx.Repo.Repository.ID, BranchName: form.BranchName, CanPush: form.EnablePush, EnableWhitelist: form.EnablePush && form.EnablePushWhitelist, EnableMergeWhitelist: form.EnableMergeWhitelist, WhitelistDeployKeys: form.EnablePush && form.EnablePushWhitelist && form.PushWhitelistDeployKeys, EnableStatusCheck: form.EnableStatusCheck, StatusCheckContexts: form.StatusCheckContexts, EnableApprovalsWhitelist: form.EnableApprovalsWhitelist, RequiredApprovals: requiredApprovals, BlockOnRejectedReviews: form.BlockOnRejectedReviews, BlockOnOfficialReviewRequests: form.BlockOnOfficialReviewRequests, DismissStaleApprovals: form.DismissStaleApprovals, RequireSignedCommits: form.RequireSignedCommits, ProtectedFilePatterns: form.ProtectedFilePatterns, UnprotectedFilePatterns: form.UnprotectedFilePatterns, BlockOnOutdatedBranch: form.BlockOnOutdatedBranch, } err = models.UpdateProtectBranch(ctx.Repo.Repository, protectBranch, models.WhitelistOptions{ UserIDs: whitelistUsers, TeamIDs: whitelistTeams, MergeUserIDs: mergeWhitelistUsers, MergeTeamIDs: mergeWhitelistTeams, ApprovalsUserIDs: approvalsWhitelistUsers, ApprovalsTeamIDs: approvalsWhitelistTeams, }) if err != nil { ctx.Error(http.StatusInternalServerError, "UpdateProtectBranch", err) return } if err = pull_service.CheckPrsForBaseBranch(ctx.Repo.Repository, protectBranch.BranchName); err != nil { ctx.Error(http.StatusInternalServerError, "CheckPrsForBaseBranch", err) return } // Reload from db to get all whitelists bp, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, form.BranchName) if err != nil { ctx.Error(http.StatusInternalServerError, "GetProtectedBranchByID", err) return } if bp == nil || bp.RepoID != ctx.Repo.Repository.ID { ctx.Error(http.StatusInternalServerError, "New branch protection not found", err) return } ctx.JSON(http.StatusCreated, convert.ToBranchProtection(bp)) } // EditBranchProtection edits a branch protection for a repo func EditBranchProtection(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/branch_protections/{name} repository repoEditBranchProtection // --- // summary: Edit a branch protections for a repository. Only fields that are set will be changed // consumes: // - application/json // 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: name // in: path // description: name of protected branch // type: string // required: true // - name: body // in: body // schema: // "$ref": "#/definitions/EditBranchProtectionOption" // responses: // "200": // "$ref": "#/responses/BranchProtection" // "404": // "$ref": "#/responses/notFound" // "422": // "$ref": "#/responses/validationError" form := web.GetForm(ctx).(*api.EditBranchProtectionOption) repo := ctx.Repo.Repository bpName := ctx.Params(":name") protectBranch, err := models.GetProtectedBranchBy(repo.ID, bpName) if err != nil { ctx.Error(http.StatusInternalServerError, "GetProtectedBranchByID", err) return } if protectBranch == nil || protectBranch.RepoID != repo.ID { ctx.NotFound() return } if form.EnablePush != nil { if !*form.EnablePush { protectBranch.CanPush = false protectBranch.EnableWhitelist = false protectBranch.WhitelistDeployKeys = false } else { protectBranch.CanPush = true if form.EnablePushWhitelist != nil { if !*form.EnablePushWhitelist { protectBranch.EnableWhitelist = false protectBranch.WhitelistDeployKeys = false } else { protectBranch.EnableWhitelist = true if form.PushWhitelistDeployKeys != nil { protectBranch.WhitelistDeployKeys = *form.PushWhitelistDeployKeys } } } } } if form.EnableMergeWhitelist != nil { protectBranch.EnableMergeWhitelist = *form.EnableMergeWhitelist } if form.EnableStatusCheck != nil { protectBranch.EnableStatusCheck = *form.EnableStatusCheck } if protectBranch.EnableStatusCheck { protectBranch.StatusCheckContexts = form.StatusCheckContexts } if form.RequiredApprovals != nil && *form.RequiredApprovals >= 0 { protectBranch.RequiredApprovals = *form.RequiredApprovals } if form.EnableApprovalsWhitelist != nil { protectBranch.EnableApprovalsWhitelist = *form.EnableApprovalsWhitelist } if form.BlockOnRejectedReviews != nil { protectBranch.BlockOnRejectedReviews = *form.BlockOnRejectedReviews } if form.BlockOnOfficialReviewRequests != nil { protectBranch.BlockOnOfficialReviewRequests = *form.BlockOnOfficialReviewRequests } if form.DismissStaleApprovals != nil { protectBranch.DismissStaleApprovals = *form.DismissStaleApprovals } if form.RequireSignedCommits != nil { protectBranch.RequireSignedCommits = *form.RequireSignedCommits } if form.ProtectedFilePatterns != nil { protectBranch.ProtectedFilePatterns = *form.ProtectedFilePatterns } if form.UnprotectedFilePatterns != nil { protectBranch.UnprotectedFilePatterns = *form.UnprotectedFilePatterns } if form.BlockOnOutdatedBranch != nil { protectBranch.BlockOnOutdatedBranch = *form.BlockOnOutdatedBranch } var whitelistUsers []int64 if form.PushWhitelistUsernames != nil { whitelistUsers, err = user_model.GetUserIDsByNames(form.PushWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) return } pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-11-24 00:01+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: templates/settings.php:4 msgid "WebDAV URL: http://" msgstr ""
# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-11-24 00:01+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: templates/settings.php:4 msgid "WebDAV URL: http://" msgstr ""