1
0

github.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * Copyright 2010-2020 Gildas Lormeau
  3. * contact : gildas.lormeau <at> gmail.com
  4. *
  5. * This file is part of SingleFile.
  6. *
  7. * The code in this file is free software: you can redistribute it and/or
  8. * modify it under the terms of the GNU Affero General Public License
  9. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * The code in this file is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  15. * General Public License for more details.
  16. *
  17. * As additional permission under GNU AGPL version 3 section 7, you may
  18. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  19. * AGPL normally required by section 4, provided you include this license
  20. * notice and a URL through which recipients can access the Corresponding
  21. * Source.
  22. */
  23. /* global fetch */
  24. export { pushGitHub };
  25. let pendingPush;
  26. async function pushGitHub(token, userName, repositoryName, branchName, path, content) {
  27. while (pendingPush) {
  28. await pendingPush;
  29. }
  30. pendingPush = async () => {
  31. try {
  32. const refData = await getRefData(`heads/${branchName}`);
  33. const commitSHA = refData.object.sha;
  34. let commitData = await getCommitData(commitSHA);
  35. const treeData = await createTree({ path, content }, commitData.tree.sha);
  36. commitData = await commit(commitSHA, treeData.sha);
  37. await updateHead(commitData.sha);
  38. } finally {
  39. pendingPush = null;
  40. }
  41. };
  42. await pendingPush();
  43. function getRefData(ref) {
  44. return fetchAPI(`refs/${ref}`);
  45. }
  46. function getCommitData(commitSHA) {
  47. return fetchAPI(`commits/${commitSHA}`);
  48. }
  49. function createTree({ path, content }, treeSHA) {
  50. return fetchAPI("trees", {
  51. tree: [{ path, content, mode: "100644" }],
  52. base_tree: treeSHA
  53. });
  54. }
  55. function commit(commitSHA, treeSHA, message = "") {
  56. return fetchAPI("commits", {
  57. message,
  58. parents: [commitSHA],
  59. tree: treeSHA
  60. });
  61. }
  62. function updateHead(commitSHA) {
  63. return fetchAPI(`refs/heads/${branchName}`, {
  64. sha: commitSHA
  65. }, "patch", [["accept", "application/vnd.github.v3+json"]]);
  66. }
  67. async function fetchAPI(path, data, method, extraHeaders = []) {
  68. const response = await fetch(`https://api.github.com/repos/${userName}/${repositoryName}/git/${path}`, {
  69. method: method ? method.toUpperCase() : data ? "POST" : "GET",
  70. headers: new Map([["authorization", `token ${token}`]].concat(extraHeaders)),
  71. body: data ? JSON.stringify(data) : null
  72. });
  73. const responseData = await response.json();
  74. if (response.status < 400) {
  75. return responseData;
  76. } else {
  77. throw new Error(responseData.message);
  78. }
  79. }
  80. }