UNPKG

abap-adt-api

Version:

Interface to Abap Developer Tools webservice

301 lines (300 loc) 13.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.switchRepoBranch = exports.remoteRepoInfo = exports.stageRepo = exports.pushRepo = exports.checkRepo = exports.unlinkRepo = exports.pullRepo = exports.createRepo = exports.externalRepoInfo = exports.gitRepos = void 0; const utilities_1 = require("../utilities"); const AdtException_1 = require("../AdtException"); const parseDate = (d) => { const match = d.match(/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/); if (!match) return new Date(); // wrong but valid const [Y, M, D, h, m, s] = match.slice(1); return new Date(Date.UTC((0, utilities_1.toInt)(Y), (0, utilities_1.toInt)(M) - 1, (0, utilities_1.toInt)(D), (0, utilities_1.toInt)(h), (0, utilities_1.toInt)(m), (0, utilities_1.toInt)(s))); }; async function gitRepos(h) { const headers = { Accept: "application/abapgit.adt.repos.v2+xml" }; const response = await h.request(`/sap/bc/adt/abapgit/repos`, { headers }); const raw = (0, utilities_1.parse)(response.body, { ignoreAttributes: false, parseAttributeValue: false, parseTagValue: false, removeNSPrefix: true }); return (0, utilities_1.xmlArray)(raw, "repositories", "repository").map((x) => { const { key, package: sapPackage, url, status, status_text, } = x; // tslint:disable: variable-name const branch_name = x.branch_name || x.branchName || ""; const created_by = x.created_by || x.createdBy || ""; const created_at = x.created_at || x.createdAt || ""; const created_email = x.created_email || x.createdEmail || ""; const deserialized_by = x.deserialized_by || x.deserializedBy || ""; const deserialized_email = x.deserialized_email || x.deserializedEmail || ""; const deserialized_at = x.deserialized_at || x.deserializedAt || ""; const links = (0, utilities_1.xmlArray)(x, "link").map(utilities_1.xmlNodeAttr); const repo = { key, sapPackage, url, branch_name, created_by, created_at: parseDate(created_at), created_email, deserialized_by, deserialized_email, deserialized_at: deserialized_at && parseDate(deserialized_at), status, status_text, links, }; return repo; }); } exports.gitRepos = gitRepos; async function externalRepoInfo(h, repourl, user = "", password = "") { const headers = { "Content-Type": "application/abapgit.adt.repo.info.ext.request.v2+xml", Accept: "application/abapgit.adt.repo.info.ext.response.v2+xml", }; const body = `<?xml version="1.0" ?> <abapgitexternalrepo:externalRepoInfoRequest xmlns:abapgitexternalrepo="http://www.sap.com/adt/abapgit/externalRepo"> <abapgitexternalrepo:url>${repourl}</abapgitexternalrepo:url> <abapgitexternalrepo:user>${user}</abapgitexternalrepo:user> <abapgitexternalrepo:password>${password}</abapgitexternalrepo:password> </abapgitexternalrepo:externalRepoInfoRequest>`; const response = await h.request(`/sap/bc/adt/abapgit/externalrepoinfo`, { method: "POST", body, headers, }); const raw = (0, utilities_1.fullParse)(response.body, { removeNSPrefix: true }); // tslint:disable-next-line: variable-name const access_mode = (0, utilities_1.xmlNode)(raw, "externalRepoInfo", "accessMode"); const branches = (0, utilities_1.xmlArray)(raw, "externalRepoInfo", "branch").map((branch) => ({ name: branch.name, type: branch.type, sha1: branch.sha1, display_name: branch.displayName, is_head: (0, utilities_1.boolFromAbap)(branch && branch.is_head), })); return { access_mode, branches }; } exports.externalRepoInfo = externalRepoInfo; const parseObjects = (body) => { const raw = (0, utilities_1.fullParse)(body); return (0, utilities_1.xmlArray)(raw, "objects", "object").map((r) => { const { type, name, package: pkg, status, msgType, msgText, } = r; const obj = { obj_type: type, obj_name: name, package: pkg, obj_status: status, msg_type: msgType, msg_text: msgText, }; }); }; async function createRepo(h, packageName, repourl, branch = "refs/heads/master", transport = "", user = "", password = "") { const headers = { "Content-Type": "application/abapgit.adt.repo.v3+xml", }; const body = `<?xml version="1.0" ?> <abapgitrepo:repository xmlns:abapgitrepo="http://www.sap.com/adt/abapgit/repositories"> <abapgitrepo:package>${packageName}</abapgitrepo:package> <abapgitrepo:url>${repourl}</abapgitrepo:url> <abapgitrepo:branchName>${branch}</abapgitrepo:branchName> <abapgitrepo:transportRequest>${transport}</abapgitrepo:transportRequest> <abapgitrepo:remoteUser>${user}</abapgitrepo:remoteUser> <abapgitrepo:remotePassword>${password}</abapgitrepo:remotePassword> </abapgitrepo:repository>`; const response = await h.request(`/sap/bc/adt/abapgit/repos`, { method: "POST", body, headers, // encodeEntity? }); return parseObjects(response.body); } exports.createRepo = createRepo; async function pullRepo(h, repoId, branch = "refs/heads/master", transport = "", user = "", password = "") { const headers = { "Content-Type": "application/abapgit.adt.repo.v3+xml", }; branch = `<abapgitrepo:branchName>${branch}</abapgitrepo:branchName>`; transport = transport ? `<abapgitrepo:transportRequest>${transport}</abapgitrepo:transportRequest>` : ""; user = user ? `<abapgitrepo:remoteUser>${user}</abapgitrepo:remoteUser>` : ""; password = password ? `<abapgitrepo:remotePassword>${password}</abapgitrepo:remotePassword>` : ""; const body = `<?xml version="1.0" ?><abapgitrepo:repository xmlns:abapgitrepo="http://www.sap.com/adt/abapgit/repositories"> ${branch}${transport}${user}${password}</abapgitrepo:repository>`; const response = await h.request(`/sap/bc/adt/abapgit/repos/${repoId}/pull`, { method: "POST", body, headers, }); return parseObjects(response.body); } exports.pullRepo = pullRepo; async function unlinkRepo(h, repoId) { const headers = { "Content-Type": "application/abapgit.adt.repo.v3+xml", }; await h.request(`/sap/bc/adt/abapgit/repos/${repoId}`, { method: "DELETE", headers, }); } exports.unlinkRepo = unlinkRepo; const deserializeStaging = (body) => { const raw = (0, utilities_1.xmlNode)((0, utilities_1.fullParse)(body), "abapgitstaging:abapgitstaging"); const parsefile = (x) => ({ ...(0, utilities_1.stripNs)((0, utilities_1.xmlNodeAttr)(x)), links: (0, utilities_1.xmlArray)(x, "atom:link") .map(utilities_1.xmlNodeAttr) .map(utilities_1.stripNs) .map((l) => ({ ...l, href: l.href })), }); const parseObject = (x) => { const attrs = (0, utilities_1.stripNs)((0, utilities_1.xmlNodeAttr)(x)); const abapGitFiles = (0, utilities_1.xmlArray)(x, "abapgitstaging:abapgitfile").map(parsefile); return { ...attrs, abapGitFiles }; }; const unstaged = (0, utilities_1.xmlArray)(raw, "abapgitstaging:unstaged_objects", "abapgitstaging:abapgitobject").map(parseObject); const staged = (0, utilities_1.xmlArray)(raw, "abapgitstaging:staged_objects", "abapgitstaging:abapgitobject").map(parseObject); const ignored = (0, utilities_1.xmlArray)(raw, "abapgitstaging:ignored_objects", "abapgitstaging:abapgitobject").map(parseObject); const commentNode = (0, utilities_1.xmlNode)(raw, "abapgitstaging:abapgit_comment"); const extractUser = (p) => (0, utilities_1.stripNs)((0, utilities_1.xmlNodeAttr)((0, utilities_1.xmlNode)(commentNode, p))); const comment = commentNode["@_abapgitstaging:comment"] || ""; const author = extractUser("abapgitstaging:author"); const committer = extractUser("abapgitstaging:author"); const result = { staged, unstaged, ignored, comment, author, committer, }; return result; }; const serializeStaging = (s) => { const formatFile = (f) => { const { links, ...rest } = f; return ` <abapgitstaging:abapgitfile ${(0, utilities_1.toXmlAttributes)(rest, "abapgitstaging")}>${links .map((l) => ({ ...l, href: (0, utilities_1.encodeEntity)(l.href) })) .map((l) => `<atom:link ${(0, utilities_1.toXmlAttributes)(l, "")}/>`) .join("")} </abapgitstaging:abapgitfile>`; }; const formatObject = (obj) => { const { abapGitFiles, wbkey, ...rest } = obj; return `<abapgitstaging:abapgitobject ${(0, utilities_1.toXmlAttributes)(rest, "adtcore")} abapgitstaging:wbkey="${obj.wbkey}"> ${obj.abapGitFiles.map(formatFile).join("")} </abapgitstaging:abapgitobject>`; }; const formatObjects = (objects, root) => { if (!objects.length) return `<${root}/>`; return `<${root}>${objects.map(formatObject).join("")}</${root}>`; }; const unstaged = formatObjects(s.unstaged, "abapgitstaging:unstaged_objects"); const staged = formatObjects(s.staged, "abapgitstaging:staged_objects"); const ignored = formatObjects(s.ignored, "abapgitstaging:ignored_objects"); const comment = `<abapgitstaging:abapgit_comment abapgitstaging:comment="${s.comment}"> <abapgitstaging:author abapgitstaging:name="${s.author.name}" abapgitstaging:email="${s.author.email}"/> <abapgitstaging:committer abapgitstaging:name="${s.committer.name}" abapgitstaging:email="${s.committer.email}"/> </abapgitstaging:abapgit_comment> `; return `<?xml version="1.0" encoding="UTF-8"?> <abapgitstaging:abapgitstaging xmlns:abapgitstaging="http://www.sap.com/adt/abapgit/staging" xmlns:adtcore="http://www.sap.com/adt/core" xmlns:atom="http://www.w3.org/2005/Atom"> ${unstaged} ${staged} ${ignored} ${comment} </abapgitstaging:abapgitstaging>`; }; async function checkRepo(h, repo, user = "", password = "") { const clink = repo.links.find((l) => l.type === "check_link"); if (!(clink === null || clink === void 0 ? void 0 : clink.href)) throw (0, AdtException_1.adtException)("Check link not found"); const headers = { Accept: "text/plain", }; if (user) headers.Username = user; if (password) headers.Password = (0, utilities_1.btoa)(password); await h.request(clink.href, { method: "POST", headers }); } exports.checkRepo = checkRepo; async function pushRepo(h, repo, staging, user = "", password = "") { const link = repo.links.find((l) => l.type === "push_link"); if (!(link === null || link === void 0 ? void 0 : link.href)) throw (0, AdtException_1.adtException)("Push link not found"); const headers = { Accept: "application/abapgit.adt.repo.stage.v1+xml", }; headers["Content-Type"] = headers.Accept; if (user) headers.Username = user; if (password) headers.Password = (0, utilities_1.btoa)(password); const body = serializeStaging(staging); await h.request(link.href, { method: "POST", headers, body }); } exports.pushRepo = pushRepo; async function stageRepo(h, repo, user = "", password = "") { const link = repo.links.find((l) => l.type === "stage_link"); if (!(link === null || link === void 0 ? void 0 : link.href)) throw (0, AdtException_1.adtException)("Stage link not found"); const headers = { "Content-Type": "application/abapgit.adt.repo.stage.v1+xml", }; if (user) headers.Username = user; if (password) headers.Password = (0, utilities_1.btoa)(password); const resp = await h.request(link.href, { headers }); return deserializeStaging(resp.body); } exports.stageRepo = stageRepo; /** * @deprecated since 1.2.1, duplicate of externalRepoInfo */ async function remoteRepoInfo(h, repo, user = "", password = "") { var _a; const headers = { "Content-Type": "application/abapgit.adt.repo.info.ext.request.v1+xml", Accept: "application/abapgit.adt.repo.info.ext.response.v1+xml", }; const body = `<?xml version="1.0" encoding="UTF-8"?> <repository_ext> <url>${repo.url}</url> <user>${user}</user> <password>${password}</password> </repository_ext>`; const resp = await h.request("/sap/bc/adt/abapgit/externalrepoinfo", { headers, body, method: "POST", }); const raw = (_a = (0, utilities_1.parse)(resp.body)) === null || _a === void 0 ? void 0 : _a.repository_external; const { access_mode, branches } = raw; return { access_mode, branches: (0, utilities_1.xmlArray)(branches, "branch"), }; } exports.remoteRepoInfo = remoteRepoInfo; async function switchRepoBranch(h, repo, branch, create = false, user = "", password = "") { const headers = {}; if (user) headers.Username = user; if (password) headers.Password = (0, utilities_1.btoa)(password); await h.request(`/sap/bc/adt/abapgit/repos/${repo.key}/branches/${encodeURIComponent(branch)}?create=${create}`, { headers, method: "POST", }); } exports.switchRepoBranch = switchRepoBranch;