├── .github └── workflows │ └── update-generated-sources.yml ├── .gitmodules ├── com.visualstudio.code-oss.yml ├── flathub.json ├── generated-sources.json ├── install-data.py ├── patches ├── ipc-sockets-paths-flatpak.patch └── vscodium-custom-gallery.patch └── update-generated-sources.sh /.github/workflows/update-generated-sources.yml: -------------------------------------------------------------------------------- 1 | name: Update generated sources 2 | on: pull_request 3 | jobs: 4 | update-generated-sources: 5 | runs-on: ubuntu-latest 6 | if: github.event.pull_request.user.login == 'flathubbot' 7 | steps: 8 | - name: Install dependencies 9 | run: | 10 | sudo apt install -y \ 11 | python3-yaml \ 12 | python3-aiohttp \ 13 | jq 14 | 15 | - name: Checkout repository 16 | uses: actions/checkout@v3 17 | with: 18 | ref: ${{ github.event.pull_request.head.ref }} 19 | submodules: true 20 | 21 | - name: Update generated sources 22 | env: 23 | GIT_AUTHOR_NAME: Flatpak External Data Checker 24 | GIT_COMMITTER_NAME: Flatpak External Data Checker 25 | GIT_AUTHOR_EMAIL: ${{ github.actor }}@users.noreply.github.com 26 | GIT_COMMITTER_EMAIL: ${{ github.actor }}@users.noreply.github.com 27 | EMAIL: ${{ github.actor }}@users.noreply.github.com 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | run: | 30 | set -e 31 | ./update-generated-sources.sh 32 | git push 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "shared-modules"] 2 | path = shared-modules 3 | url = https://github.com/flathub/shared-modules.git 4 | [submodule "wrapper"] 5 | path = wrapper 6 | url = https://github.com/flathub/ide-flatpak-wrapper.git 7 | [submodule "tools"] 8 | path = tools 9 | url = https://github.com/flatpak/flatpak-builder-tools.git 10 | -------------------------------------------------------------------------------- /com.visualstudio.code-oss.yml: -------------------------------------------------------------------------------- 1 | id: com.visualstudio.code-oss 2 | sdk: org.freedesktop.Sdk 3 | runtime: org.freedesktop.Sdk 4 | runtime-version: '22.08' 5 | finish-args: 6 | - --share=ipc 7 | - --socket=x11 8 | - --socket=wayland 9 | - --device=dri 10 | - --allow=devel 11 | - --socket=pulseaudio 12 | - --share=network 13 | - --socket=ssh-auth 14 | - --talk-name=org.freedesktop.secrets # doesn't work well with secrets portal 15 | - --talk-name=org.freedesktop.Notifications 16 | - --talk-name=org.freedesktop.Flatpak 17 | - --filesystem=host 18 | command: code-oss 19 | rename-desktop-file: code-oss.desktop 20 | rename-appdata-file: code-oss.appdata.xml 21 | rename-icon: code-oss 22 | sdk-extensions: 23 | - org.freedesktop.Sdk.Extension.node16 24 | build-options: 25 | append-path: /usr/lib/sdk/node16/bin 26 | separate-locales: false 27 | add-extensions: 28 | com.visualstudio.code.tool: 29 | directory: tools 30 | subdirectories: true 31 | version: '22.08' 32 | add-ld-path: lib 33 | no-autodownload: true 34 | modules: 35 | 36 | - shared-modules/libsecret/libsecret.json 37 | 38 | - name: Pillow 39 | buildsystem: simple 40 | build-commands: 41 | - python3 setup.py build -j${FLATPAK_BUILDER_N_JOBS} 42 | - python3 setup.py install --prefix=${FLATPAK_DEST} --root=/ 43 | cleanup: 44 | - '*' 45 | sources: 46 | - type: archive 47 | url: https://files.pythonhosted.org/packages/bc/07/830784e061fb94d67649f3e438ff63cfb902dec6d48ac75aeaaac7c7c30e/Pillow-9.4.0.tar.gz 48 | sha256: a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e 49 | x-checker-data: 50 | type: pypi 51 | name: Pillow 52 | 53 | - name: vscode 54 | build-options: 55 | env: 56 | TMPDIR: /run/build/vscode/flatpak-node/tmp 57 | XDG_CACHE_HOME: /run/build/vscode/flatpak-node/cache 58 | DEBUG: electron-rebuild,electron-builder 59 | VSCODE_QUALITY: stable 60 | # NOTE Looks like node builds with openssl3 won't work without this option 61 | NODE_OPTIONS: --openssl-legacy-provider 62 | arch: 63 | arm: {env: {earch: armv7l, suffix: -armv7l}} 64 | aarch64: {env: {earch: arm64, suffix: -arm64}} 65 | i386: {env: {earch: ia32, suffix: -ia32}} 66 | x86_64: {env: {earch: x64, suffix: ''}} 67 | buildsystem: simple 68 | build-commands: 69 | # Prepare 70 | - | 71 | set -e 72 | mv product.json product.orig.json 73 | jq \ 74 | --argfile vscodium_product ../vscodium/product.json \ 75 | ' 76 | .quality="'"${VSCODE_QUALITY}"'" | 77 | .commit="'"$(git rev-parse HEAD)"'" | 78 | .date="'"$(date -u +'%FT%TZ')"'" | 79 | .extensionsGallery.serviceUrl="https://open-vsx.org/vscode/gallery" | 80 | .extensionsGallery.itemUrl="https://open-vsx.org/vscode/item" | 81 | .linkProtectionTrustedDomains=["https://open-vsx.org"] | 82 | .extensionEnabledApiProposals=$vscodium_product["extensionEnabledApiProposals"] | 83 | .builtInExtensions=[] 84 | ' < product.orig.json > product.json 85 | rm product.orig.json 86 | # Build 87 | - yarn --frozen-lockfile 88 | - yarn postinstall 89 | - yarn run gulp vscode-linux-$earch-min 90 | # Install 91 | - cp -a ../VSCode-linux-$earch /app/main 92 | post-install: 93 | - ../install-data.py . /app/share 94 | - mkdir -p /app/tools 95 | subdir: main 96 | sources: 97 | - type: git 98 | url: https://github.com/microsoft/vscode.git 99 | tag: 1.74.3 100 | commit: 97dec172d3256f8ca4bfb2143f3f76b503ca0534 101 | dest: main 102 | x-checker-data: 103 | type: json 104 | url: https://api.github.com/repos/microsoft/vscode/releases/latest 105 | tag-query: .tag_name 106 | version-query: $tag 107 | timestamp-query: .published_at 108 | is-main-source: true 109 | 110 | - type: patch 111 | paths: 112 | - patches/ipc-sockets-paths-flatpak.patch 113 | - patches/vscodium-custom-gallery.patch 114 | dest: main 115 | 116 | - type: file 117 | url: https://github.com/VSCodium/vscodium/raw/1.74.3.23010/product.json 118 | sha256: 1dec09142eeb4116c1dc6ab70feb364bd315d22c6099eb94badcd711c9b59257 119 | dest: vscodium 120 | x-checker-data: 121 | type: json 122 | parent-id: vscode-git-0 123 | version-data-url: >- 124 | "https://api.github.com/repos/VSCodium/vscodium/git/refs/tags/\($parent.new.tag//$parent.current.tag)" 125 | version-query: last | .ref | sub("^refs/tags/"; "") 126 | url-query: '"https://github.com/VSCodium/vscodium/raw/\($version)/product.json"' 127 | 128 | - type: inline 129 | contents: | 130 | yarn-offline-mirror /run/build/vscode/flatpak-node/yarn-mirror 131 | --install.offline true 132 | --run.offline true 133 | dest-filename: .yarnrc 134 | 135 | - generated-sources.json 136 | 137 | - type: file 138 | path: install-data.py 139 | 140 | - name: zypak 141 | sources: 142 | - type: git 143 | url: https://github.com/refi64/zypak.git 144 | tag: v2022.04 145 | commit: 55a60d110301e8dd37b631503c3524ab7baaf7aa 146 | x-checker-data: 147 | type: git 148 | 149 | - name: wrapper 150 | buildsystem: meson 151 | config-opts: 152 | - -Deditor_binary=/app/main/code-oss 153 | - >- 154 | -Deditor_args=[ 155 | '/app/main/resources/app/out/cli.js', 156 | '--ms-enable-electron-run-as-node', 157 | '--extensions-dir', '$XDG_DATA_HOME/vscode/extensions', 158 | '--disable-crash-reporter' 159 | ] 160 | - -Dprogram_name=code-oss 161 | - -Deditor_title=Visual Studio Code Open Source 162 | - -Dzypak=enabled 163 | - >- 164 | -Denvs=[ 165 | "ELECTRON_RUN_AS_NODE=1" 166 | ] 167 | - >- 168 | -Denvs_inner=[ 169 | "ZYPAK_SPAWN_LATEST_ON_REEXEC=0" 170 | ] 171 | sources: 172 | - type: dir 173 | path: wrapper 174 | -------------------------------------------------------------------------------- /flathub.json: -------------------------------------------------------------------------------- 1 | { 2 | "disable-external-data-checker": true, 3 | "only-arches": [ 4 | "x86_64", 5 | "aarch64" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /install-data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | import subprocess 5 | import json 6 | import datetime 7 | from xml.dom import minidom 8 | from PIL import Image 9 | 10 | FLATPAK_ID = os.environ.get('FLATPAK_ID') 11 | 12 | EXTRA_DESCRIPTION = [ 13 | """This open source build of Visual Studio Code is not supported by Microsoft. 14 | Issues should be reported through linked bug tracker.""" 15 | ] 16 | 17 | EXTRA_URLS = { 18 | 'bugtracker': f'https://github.com/flathub/{FLATPAK_ID}/issues' 19 | } 20 | 21 | OARS_DATA = { 22 | 'social-chat': 'intense', 23 | 'social-info': 'intense', 24 | 'social-audio': 'intense', 25 | 'social-contacts': 'intense', 26 | } 27 | 28 | def configure_file(product, input_data): 29 | replacements = { 30 | 'NAME': product['applicationName'], 31 | 'NAME_SHORT': product['nameShort'], 32 | 'NAME_LONG': product['nameLong'], 33 | 'EXEC': product['applicationName'], 34 | 'ICON': product['applicationName'], 35 | 'URLPROTOCOL': product['urlProtocol'], 36 | 'LICENSE': product['licenseName'], 37 | } 38 | output = input_data 39 | for key, value in replacements.items(): 40 | output = output.replace(f'@@{key}@@', value) 41 | return output 42 | 43 | def install_file(product, src_file, dst_file): 44 | with open(src_file, 'r') as i: 45 | os.makedirs(os.path.dirname(dst_file), exist_ok=True) 46 | with open(dst_file, 'w') as o: 47 | o.write(configure_file(product, i.read())) 48 | 49 | def update_appdata(srcdir, appdata_path): 50 | appdata = minidom.parse(appdata_path) 51 | component = appdata.documentElement 52 | 53 | with open(os.path.join(srcdir, 'package.json'), 'r') as p: 54 | package = json.load(p) 55 | 56 | version = package['version'] 57 | git_timestamp = subprocess.run(['git', 'show', '-s', '--format=%ct'], 58 | cwd=srcdir, check=True, text=True, 59 | stdout=subprocess.PIPE).stdout 60 | date = datetime.datetime.fromtimestamp(int(git_timestamp)).date().isoformat() 61 | 62 | releases = appdata.createElement('releases') 63 | release = appdata.createElement('release') 64 | release.setAttribute('version', version) 65 | release.setAttribute('date', date) 66 | releases.appendChild(release) 67 | component.appendChild(releases) 68 | 69 | for url_type, url_href in EXTRA_URLS.items(): 70 | url = appdata.createElement('url') 71 | url.setAttribute('type', url_type) 72 | url.appendChild(appdata.createTextNode(url_href)) 73 | component.appendChild(url) 74 | 75 | content_rating = appdata.createElement('content_rating') 76 | content_rating.setAttribute('type', 'oars-1.1') 77 | for attr, value in OARS_DATA.items(): 78 | content_attribute = appdata.createElement('content_attribute') 79 | content_attribute.setAttribute('id', attr) 80 | content_attribute.appendChild(appdata.createTextNode(value)) 81 | content_rating.appendChild(content_attribute) 82 | component.appendChild(content_rating) 83 | 84 | description = component.getElementsByTagName('description')[0] 85 | for descr in EXTRA_DESCRIPTION: 86 | paragraph = appdata.createElement('p') 87 | paragraph.appendChild(appdata.createTextNode(descr)) 88 | description.appendChild(paragraph) 89 | 90 | with open(appdata_path, 'w') as o: 91 | o.write(appdata.toxml(encoding='UTF-8').decode()) 92 | 93 | def install_desktop_data(srcdir, datadir): 94 | with open(os.path.join(srcdir, 'product.json'), 'r') as p: 95 | product = json.load(p) 96 | appname = product['applicationName'] 97 | 98 | with Image.open(os.path.join(srcdir, 'resources', 'linux', 'code.png')) as icon: 99 | for s in [16, 24, 32, 48, 64, 128, 192, 256, 512]: 100 | dest = os.path.join(datadir, 'icons', 'hicolor', f'{s}x{s}', 'apps', f'{appname}.png') 101 | os.makedirs(os.path.dirname(dest), exist_ok=True) 102 | icon.resize((s, s), resample=Image.LANCZOS).save(dest) 103 | 104 | install_file(product, 105 | os.path.join(srcdir, 'resources', 'linux', 'code.desktop'), 106 | os.path.join(datadir, 'applications', f'{appname}.desktop')) 107 | install_file(product, 108 | os.path.join(srcdir, 'resources', 'linux', 'code-url-handler.desktop'), 109 | os.path.join(datadir, 'applications', f'{FLATPAK_ID}-url-handler.desktop')) 110 | appdata_path = os.path.join(datadir, 'appdata', f'{appname}.appdata.xml') 111 | install_file(product, 112 | os.path.join(srcdir, 'resources', 'linux', 'code.appdata.xml'), 113 | appdata_path) 114 | update_appdata(srcdir, appdata_path) 115 | 116 | def main(): 117 | srcdir = sys.argv[1] 118 | datadir = sys.argv[2] 119 | install_desktop_data(srcdir, datadir) 120 | 121 | if __name__ == '__main__': 122 | main() -------------------------------------------------------------------------------- /patches/ipc-sockets-paths-flatpak.patch: -------------------------------------------------------------------------------- 1 | diff --git a/extensions/git/src/ipc/ipcServer.ts b/extensions/git/src/ipc/ipcServer.ts 2 | index 5cea9faf98f..0e4271162bc 100644 3 | --- a/extensions/git/src/ipc/ipcServer.ts 4 | +++ b/extensions/git/src/ipc/ipcServer.ts 5 | @@ -16,8 +16,14 @@ function getIPCHandlePath(id: string): string { 6 | return `\\\\.\\pipe\\vscode-git-${id}-sock`; 7 | } 8 | 9 | - if (process.env['XDG_RUNTIME_DIR']) { 10 | - return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-${id}.sock`); 11 | + const xdgRuntimeDir = process.env['XDG_RUNTIME_DIR']; 12 | + if (xdgRuntimeDir) { 13 | + const flatpakID = process.env['FLATPAK_ID']; 14 | + if (flatpakID) { 15 | + return path.join(xdgRuntimeDir, 'app', flatpakID, `vscode-git-${id}.sock`); 16 | + } else { 17 | + return path.join(xdgRuntimeDir, `vscode-git-${id}.sock`); 18 | + } 19 | } 20 | 21 | return path.join(os.tmpdir(), `vscode-git-${id}.sock`); 22 | diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts 23 | index ae2d2a60c4c..54f68436ece 100644 24 | --- a/src/vs/base/parts/ipc/node/ipc.net.ts 25 | +++ b/src/vs/base/parts/ipc/node/ipc.net.ts 26 | @@ -477,6 +477,19 @@ const safeIpcPathLengths: { [platform: number]: number } = { 27 | [Platform.Mac]: 103 28 | }; 29 | 30 | +export function getXdgSocketPath(socketName: string): string { 31 | + if (XDG_RUNTIME_DIR) { 32 | + const flatpakID = process.env['FLATPAK_ID']; 33 | + if (flatpakID) { 34 | + return join(XDG_RUNTIME_DIR, 'app', flatpakID, socketName); 35 | + } else { 36 | + return join(XDG_RUNTIME_DIR, socketName); 37 | + } 38 | + } else { 39 | + return join('/run', 'user', process.getuid().toString(), socketName); 40 | + } 41 | +} 42 | + 43 | export function createRandomIPCHandle(): string { 44 | const randomSuffix = generateUuid(); 45 | 46 | @@ -489,7 +502,7 @@ export function createRandomIPCHandle(): string { 47 | // XDG_RUNTIME_DIR over tmpDir 48 | let result: string; 49 | if (XDG_RUNTIME_DIR) { 50 | - result = join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`); 51 | + result = getXdgSocketPath(`vscode-ipc-${randomSuffix}.sock`); 52 | } else { 53 | result = join(tmpdir(), `vscode-ipc-${randomSuffix}.sock`); 54 | } 55 | @@ -513,7 +526,7 @@ export function createStaticIPCHandle(directoryPath: string, type: string, versi 56 | // unless portable 57 | let result: string; 58 | if (XDG_RUNTIME_DIR && !process.env['VSCODE_PORTABLE']) { 59 | - result = join(XDG_RUNTIME_DIR, `vscode-${scope.substr(0, 8)}-${version}-${type}.sock`); 60 | + result = getXdgSocketPath(`vscode-${scope.substr(0, 8)}-${version}-${type}.sock`); 61 | } else { 62 | result = join(directoryPath, `${version}-${type}.sock`); 63 | } 64 | -------------------------------------------------------------------------------- /patches/vscodium-custom-gallery.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts 2 | index ef798fa..5a0550b 100644 3 | --- a/src/vs/platform/product/common/product.ts 4 | +++ b/src/vs/platform/product/common/product.ts 5 | @@ -5,3 +5,4 @@ 6 | 7 | -import { globals } from 'vs/base/common/platform'; 8 | +import { AppResourcePath, FileAccess } from 'vs/base/common/network'; 9 | +import { globals, isWindows } from 'vs/base/common/platform'; 10 | import { env } from 'vs/base/common/process'; 11 | @@ -9,2 +10,3 @@ import { IProductConfiguration } from 'vs/base/common/product'; 12 | import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes'; 13 | +import { getUserDataPath } from 'vs/platform/environment/node/userDataPath'; 14 | 15 | @@ -29,2 +31,40 @@ else if (globalThis._VSCODE_PRODUCT_JSON && globalThis._VSCODE_PACKAGE_JSON) { 16 | 17 | + // Set user-defined extension gallery 18 | + const { serviceUrl, searchUrl, itemUrl, controlUrl } = product.extensionsGallery || {} 19 | + 20 | + Object.assign(product, { 21 | + extensionsGallery: { 22 | + serviceUrl: env['VSCODE_GALLERY_SERVICE_URL'] || serviceUrl, 23 | + searchUrl: env['VSCODE_GALLERY_SEARCH_URL'] || searchUrl, 24 | + itemUrl: env['VSCODE_GALLERY_ITEM_URL'] || itemUrl, 25 | + controlUrl: env['VSCODE_GALLERY_CONTROL_URL'] || controlUrl, 26 | + } 27 | + }) 28 | + 29 | + // Merge user-customized product.json 30 | + try { 31 | + const merge = (...objects: any[]) => 32 | + objects.reduce((result, current) => { 33 | + Object.keys(current).forEach((key) => { 34 | + if (Array.isArray(result[key]) && Array.isArray(current[key])) { 35 | + result[key] = current[key]; 36 | + } else if (typeof result[key] === 'object' && typeof current[key] === 'object') { 37 | + result[key] = merge(result[key], current[key]); 38 | + } else { 39 | + result[key] = current[key]; 40 | + } 41 | + }); 42 | + 43 | + return result; 44 | + }, {}) as any; 45 | + 46 | + const userDataPath = getUserDataPath({} as any, product.nameShort); 47 | + const userProductPath = isWindows ? `file:///${userDataPath}/product.json` : `file://${userDataPath}/product.json`; 48 | + 49 | + const userProduct = require.__$__nodeRequire(FileAccess.asFileUri(userProductPath as AppResourcePath).fsPath); 50 | + 51 | + product = merge(product, userProduct); 52 | + } catch (ex) { 53 | + } 54 | + 55 | // Running out of sources 56 | -------------------------------------------------------------------------------- /update-generated-sources.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail 4 | set -e 5 | 6 | MANIFEST_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" 7 | TOOLS_DIR="${TOOLS_DIR:-"$MANIFEST_DIR/tools"}" 8 | 9 | GENERATED_SOURCES="generated-sources.json" 10 | MANIFEST_PATH="$MANIFEST_DIR/com.visualstudio.code-oss.yml" 11 | MODULE_NAME=${MODULE_NAME:-"vscode"} 12 | 13 | MODULE_OBJ=$( 14 | python3 -c 'import sys,json,yaml; json.dump(yaml.safe_load(sys.stdin), sys.stdout)' \ 15 | < "$MANIFEST_PATH" | \ 16 | jq -e \ 17 | --arg MODULE_NAME "$MODULE_NAME" \ 18 | '.modules | map(select(objects | .name==$MODULE_NAME)) | first' 19 | ) 20 | SOURCE_OBJ=$( 21 | jq -e '.sources | map(select(objects | .type=="git")) | first' \ 22 | <<<"$MODULE_OBJ" 23 | ) 24 | 25 | SOURCE_URL="$(jq -r '.url' <<<"$SOURCE_OBJ")" 26 | SOURCE_TAG="$(jq -r '.tag' <<<"$SOURCE_OBJ")" 27 | 28 | CLONE_DIR="$(mktemp -d "${TMPDIR:-"/tmp"}/$MODULE_NAME.XXXXXX")" 29 | 30 | git clone --depth=1 --branch="$SOURCE_TAG" "$SOURCE_URL" "$CLONE_DIR" 31 | 32 | while read -r patch_path; do 33 | echo "Applying patch $patch_path" >> /dev/stderr 34 | patch -d "$CLONE_DIR" -p1 < "$MANIFEST_DIR/$patch_path" 35 | done < <( 36 | jq -r -e '.sources[] | objects | select(.type=="patch") | .path // .paths[]' \ 37 | <<<"$MODULE_OBJ" 38 | ) 39 | 40 | if [ -z "${PYTHONPATH}" ]; then 41 | export PYTHONPATH="$TOOLS_DIR/node" 42 | else 43 | export PYTHONPATH="$TOOLS_DIR/node:${PYTHONPATH}" 44 | fi 45 | 46 | python3 -m flatpak_node_generator \ 47 | --electron-node-headers \ 48 | --electron-ffmpeg=archive \ 49 | --recursive \ 50 | --output "$MANIFEST_DIR/$GENERATED_SOURCES" \ 51 | yarn "$CLONE_DIR/yarn.lock" 52 | 53 | if ! git -C "$MANIFEST_DIR" diff --exit-code -- "$GENERATED_SOURCES" >> /dev/null; then 54 | git -C "$MANIFEST_DIR" add "$GENERATED_SOURCES" 55 | git -C "$MANIFEST_DIR" commit -m "Update $GENERATED_SOURCES for $MODULE_NAME $SOURCE_TAG" 56 | fi 57 | --------------------------------------------------------------------------------