update_patches.sh 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #!/usr/bin/env bash
  2. export VSCODE_QUALITY="stable"
  3. while getopts ":i" opt; do
  4. case "$opt" in
  5. i)
  6. export VSCODE_QUALITY="insider"
  7. ;;
  8. *)
  9. ;;
  10. esac
  11. done
  12. generate_rejects() {
  13. local PATCH_FILE="$1"
  14. if ! command -v python3 >/dev/null 2>&1; then
  15. echo "python3 not found; cannot create reject files for ${PATCH_FILE}"
  16. return 1
  17. fi
  18. PATCH_FOR_REJECT="${PATCH_FILE}" python3 <<'PY'
  19. import os
  20. import pathlib
  21. import re
  22. import subprocess
  23. def chunk_needs_reject(raw_chunk: str) -> bool:
  24. """Return True when a patch chunk cannot be applied nor reversed."""
  25. chunk = raw_chunk if raw_chunk.endswith("\n") else raw_chunk + "\n"
  26. def _run_git(extra_args):
  27. return subprocess.run(
  28. ["git", "apply", "--check", "--ignore-whitespace", *extra_args],
  29. input=chunk,
  30. text=True,
  31. capture_output=True,
  32. )
  33. forward = _run_git([])
  34. if forward.returncode == 0:
  35. return False
  36. reverse = _run_git(["--reverse"])
  37. if reverse.returncode == 0:
  38. return False
  39. return True
  40. patch_path = os.environ["PATCH_FOR_REJECT"]
  41. with open(patch_path, "r", encoding="utf-8", errors="ignore") as src:
  42. content = src.read()
  43. chunks = re.split(r'(?m)^diff --git ', content)
  44. for chunk in chunks:
  45. chunk = chunk.strip()
  46. if not chunk:
  47. continue
  48. chunk = "diff --git " + chunk
  49. match = re.search(r'^diff --git a/(.*?) b/(.*?)$', chunk, re.MULTILINE)
  50. if not match:
  51. continue
  52. a_path, b_path = match.groups()
  53. candidate = b_path if b_path != "/dev/null" else a_path
  54. if candidate in ("/dev/null", ""):
  55. continue
  56. if candidate.startswith("../") or candidate.startswith("..\\") or candidate.startswith("/"):
  57. continue
  58. dest = pathlib.Path(candidate + ".rej")
  59. if not chunk_needs_reject(chunk):
  60. continue
  61. dest.parent.mkdir(parents=True, exist_ok=True)
  62. with dest.open("w", encoding="utf-8") as fh:
  63. fh.write(chunk)
  64. if not chunk.endswith("\n"):
  65. fh.write("\n")
  66. print(f"generated reject: {dest}")
  67. PY
  68. }
  69. check_file() {
  70. while [ $# -gt 1 ]; do
  71. git apply --reject "${1}"
  72. shift
  73. done
  74. if [[ -f "${1}.bak" ]]; then
  75. mv -f $1{.bak,}
  76. fi
  77. if [[ -f "${1}" ]]; then
  78. git apply --reject "../patches/helper/settings.patch"
  79. git add .
  80. git commit --no-verify -q -m "VSCODIUM HELPER"
  81. echo applying patch: "${1}"
  82. if ! git apply --ignore-whitespace "${1}"; then
  83. echo failed to apply patch "${1}"
  84. git apply --reject --verbose "${1}"
  85. if [[ -z "$( find . -name '*.rej' -print )" ]]; then
  86. echo "no .rej generated by git; creating fallback rejects for ${1}"
  87. if ! generate_rejects "${1}"; then
  88. echo "failed to generate reject files for ${1}"
  89. exit 1
  90. fi
  91. if [[ -z "$( find . -name '*.rej' -print )" ]]; then
  92. echo "still no .rej after attempting to create them for ${1}"
  93. exit 1
  94. fi
  95. fi
  96. while [[ -n "$( find . -name '*.rej' -print )" ]]; do
  97. read -rp "Press any key when the conflict have been resolved..." -n1 -s
  98. echo
  99. done
  100. git restore .vscode/settings.json
  101. git add .
  102. git diff --staged -U1 > "${1}"
  103. fi
  104. git add .
  105. git reset -q --hard HEAD~
  106. fi
  107. }
  108. cd vscode || { echo "'vscode' dir not found"; exit 1; }
  109. git add .
  110. git reset -q --hard HEAD
  111. while [[ -n "$( git log -1 | grep "VSCODIUM HELPER" )" ]]; do
  112. git reset -q --hard HEAD~
  113. done
  114. for FILE in ../patches/*.patch; do
  115. if [[ "${FILE}" == *"/fix-policies.patch" ]]; then
  116. check_file "../patches/fix-keymap.patch" "../patches/fix-policies.patch"
  117. else
  118. check_file "${FILE}"
  119. fi
  120. done
  121. if [[ "${VSCODE_QUALITY}" == "insider" ]]; then
  122. for FILE in ../patches/insider/*.patch; do
  123. check_file "${FILE}"
  124. done
  125. fi
  126. for ARCH in alpine linux osx windows; do
  127. for FILE in "../patches/${ARCH}/"*.patch; do
  128. if [[ "${ARCH}" == "linux" && "${FILE}" == *"/arch-"* ]] || [[ "${ARCH}" == "linux" && "${FILE}" == *"/fix-dependencies.patch" ]] || [[ "${ARCH}" == "windows" && "${FILE}" == *"/cli"* ]]; then
  129. echo "skip ${FILE}"
  130. else
  131. check_file "${FILE}"
  132. fi
  133. done
  134. if [[ "${ARCH}" == "linux" ]]; then
  135. check_file "../patches/optional-tree-sitter.patch" "../patches/linux/fix-dependencies.patch"
  136. check_file "../patches/cli.patch" "../patches/linux/arch-0-support.patch"
  137. check_file "../patches/cli.patch" "../patches/linux/arch-0-support.patch" "../patches/linux/arch-1-ppc64le.patch"
  138. check_file "../patches/cli.patch" "../patches/linux/arch-0-support.patch" "../patches/linux/arch-1-ppc64le.patch" "../patches/linux/arch-2-riscv64.patch"
  139. check_file "../patches/cli.patch" "../patches/linux/arch-0-support.patch" "../patches/linux/arch-1-ppc64le.patch" "../patches/linux/arch-2-riscv64.patch" "../patches/linux/arch-3-loong64.patch"
  140. check_file "../patches/cli.patch" "../patches/linux/arch-0-support.patch" "../patches/linux/arch-1-ppc64le.patch" "../patches/linux/arch-2-riscv64.patch" "../patches/linux/arch-3-loong64.patch" "../patches/linux/arch-4-s390x.patch"
  141. elif [[ "${ARCH}" == "windows" ]]; then
  142. check_file "../patches/cli.patch" "../patches/windows/cli.patch"
  143. fi
  144. for TARGET in client reh; do
  145. for FILE in "../patches/${ARCH}/${TARGET}/"*.patch; do
  146. check_file "${FILE}"
  147. done
  148. for FILE in "../patches/${ARCH}/${TARGET}/"*/*.patch; do
  149. check_file "${FILE}"
  150. done
  151. done
  152. done