Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: electron/asar
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.2.15
Choose a base ref
...
head repository: electron/asar
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 16 commits
  • 31 files changed
  • 6 contributors

Commits on Nov 1, 2024

  1. build(deps): bump dsanders11/project-actions from 1.3.0 to 1.4.0 (#340)

    Bumps [dsanders11/project-actions](https://github.com/dsanders11/project-actions) from 1.3.0 to 1.4.0.
    - [Release notes](https://github.com/dsanders11/project-actions/releases)
    - [Changelog](https://github.com/dsanders11/project-actions/blob/main/.releaserc.json)
    - [Commits](dsanders11/project-actions@eb760c4...438b25e)
    
    ---
    updated-dependencies:
    - dependency-name: dsanders11/project-actions
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Nov 1, 2024

    Partially verified

    This commit is signed with the committer’s verified signature.
    spydon’s contribution has been verified via GPG key.
    We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
    Copy the full SHA
    546ed91 View commit details

Commits on Nov 5, 2024

  1. fix: Enable getNode to follow directory links (fixes #248) (#318)

    * Add test failing to stat symlinked file
    
    This demonstrates issue #248
    
    * (fix #248) follow directory links in getNode
    
    When called from stat, getNode should follow directory links to
    ensure that the correct node is returned. Otherwise, node.files[name]
    will be undefined, causing a TypeError.
    AndreasFranek authored Nov 5, 2024

    Partially verified

    This commit is signed with the committer’s verified signature.
    spydon’s contribution has been verified via GPG key.
    We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
    Copy the full SHA
    f30b93d View commit details

Commits on Nov 6, 2024

  1. fix: checking if symlink with same prefix points outside the directory (

    #335)
    
    fix: checking if symlink points outside the directory. (#303)
    mmaietta authored Nov 6, 2024

    Partially verified

    This commit is signed with the committer’s verified signature.
    spydon’s contribution has been verified via GPG key.
    We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
    Copy the full SHA
    9ec1830 View commit details
  2. fix: isUnpackedDir matches non-child directories that have same fol…

    …der name prefix (#333)
    
    * tmp save
    
    * update test case to test minimatch pattern
    
    * yarn prettier
    
    * remove path separator as it differs on windows
    
    * retrigger build as the timeout is unrelated to edited unit test
    
    * empty commit
    mmaietta authored Nov 6, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    spydon Lukas Klingsbo
    Copy the full SHA
    4df48cd View commit details

Commits on Nov 21, 2024

  1. test: remove unused index.test-d.ts file (#343)

    * test: remove unused index.test-d.ts file
    
    * build: remove prettier pattern with no matches
    dsanders11 authored Nov 21, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    spydon Lukas Klingsbo
    Copy the full SHA
    044fb5f View commit details

Commits on Jan 7, 2025

  1. fix: Respect unpack minimatch for symlinks within previously unpacked…

    … directories (#341)
    
    * fix: Respecting unpack configuration when considering symlinks within previously unpacked directories. This directly fixes unpacking static `.framework` modules on Mac, as otherwise codesigning will fail due to symlink files/directories not being reflected in the app.asar.unpacked directory.
    
    Added unit test with Hello.framework, generated from tutorial https://jano.dev/apple/mach-o/2024/06/28/Hello-Static-Framework.html
    Fixes: electron-userland/electron-builder#8655
    
    * adding unit test by programmatically create symlinks during test case (same approach as has been taken for filesystem UT already)
    
    * cleanup changes post-merging `main`
    mmaietta authored Jan 7, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    645b7db View commit details

Commits on Jan 11, 2025

  1. ci: switch to GHA (#342)

    * ci: switch to GHA
    
    * test: don't run symlink tests on Windows
    dsanders11 authored Jan 11, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    spydon Lukas Klingsbo
    Copy the full SHA
    76064f4 View commit details

Commits on Jan 15, 2025

  1. ci: bump continuousauth/action version (#348)

    dsanders11 authored Jan 15, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    spydon Lukas Klingsbo
    Copy the full SHA
    eb9c890 View commit details
  2. build(dev-deps): bump electron-mocha and mocha to clear audit (#349)

    dsanders11 authored Jan 15, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    spydon Lukas Klingsbo
    Copy the full SHA
    121efeb View commit details

Commits on Feb 1, 2025

  1. build(deps): bump dsanders11/project-actions from 1.4.0 to 1.5.1 (#352)

    Bumps [dsanders11/project-actions](https://github.com/dsanders11/project-actions) from 1.4.0 to 1.5.1.
    - [Release notes](https://github.com/dsanders11/project-actions/releases)
    - [Changelog](https://github.com/dsanders11/project-actions/blob/main/.releaserc.json)
    - [Commits](dsanders11/project-actions@438b25e...9c80cd3)
    
    ---
    updated-dependencies:
    - dependency-name: dsanders11/project-actions
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Feb 1, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    spydon Lukas Klingsbo
    Copy the full SHA
    8bf3b94 View commit details
  2. build(deps): bump actions/setup-node from 4.1.0 to 4.2.0 (#353)

    Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.1.0 to 4.2.0.
    - [Release notes](https://github.com/actions/setup-node/releases)
    - [Commits](actions/setup-node@39370e3...1d0ff46)
    
    ---
    updated-dependencies:
    - dependency-name: actions/setup-node
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Feb 1, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    spydon Lukas Klingsbo
    Copy the full SHA
    ad4b111 View commit details

Commits on Feb 4, 2025

  1. docs: remove grunt-asar mention (#354)

    erickzhao authored Feb 4, 2025
    Copy the full SHA
    c2a5f3a View commit details

Commits on Feb 10, 2025

  1. feat: allow providing properties (such as unpack) in ordering inp…

    …ut file (#350)
    
    * Part 1 for electron/universal#117 with updated unit test
    
    * add additional helper function
    
    * use wrapped-fs for writeFile
    
    * `yarn prettier:write`
    
    * swap to for-of loop and extract helper function `isAlreadySorted` to make it more readable
    mmaietta authored Feb 10, 2025
    Copy the full SHA
    b2f73c8 View commit details

Commits on Feb 11, 2025

  1. fix: revert "feat: allow providing properties (such as unpack) in `…

    …ordering` input file" (#356)
    
    Revert "feat: allow providing properties (such as `unpack`) in `ordering` inp…"
    
    This reverts commit b2f73c8.
    yangannyx authored Feb 11, 2025
    Copy the full SHA
    9b7ccfe View commit details

Commits on Mar 6, 2025

  1. test: add --ordering unit tests with chai (#357)

    * adding chai+snapshot functionality. adding snapshot tests to verify app with new `ordering` file unit tests
    
    * undo `await Promise.all` to return to `main` logic. Added comment saying it needs to be fixed but currently the fixture is flaky and warrants a separate investigation  ¯\_(ツ)_/¯
    
    * PR feedback. add `ordering` jsdoc and update unit tests to supply additional files to verify that "ordering" is successfully applied
    mmaietta authored Mar 6, 2025
    Copy the full SHA
    dfd30c5 View commit details

Commits on Mar 7, 2025

  1. test: add more snapshots to replace individual `assert(fs.existsSync(…

    …...))` (#359)
    mmaietta authored Mar 7, 2025
    Copy the full SHA
    c95e851 View commit details
50 changes: 0 additions & 50 deletions .circleci/config.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/add-to-project.yml
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ jobs:
creds: ${{ secrets.ECOSYSTEM_ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Add to Project
uses: dsanders11/project-actions/add-item@eb760c48894b5702398529cbb8f6e98378e315d0 # v1.3.0
uses: dsanders11/project-actions/add-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
with:
field: Opened
field-value: ${{ github.event.pull_request.created_at || github.event.issue.created_at }}
35 changes: 35 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Release

on:
push:
branches:
- main

jobs:
test:
uses: ./.github/workflows/test.yml

release:
name: Release
runs-on: ubuntu-latest
needs: test
environment: npm
permissions:
id-token: write # for CFA and npm provenance
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 20.x
cache: 'yarn'
- name: Install
run: yarn install --frozen-lockfile
- uses: continuousauth/action@4e8a2573eeb706f6d7300d6a9f3ca6322740b72d # v1.0.5
with:
project-id: ${{ secrets.CFA_PROJECT_ID }}
secret: ${{ secrets.CFA_SECRET }}
npm-token: ${{ secrets.NPM_TOKEN }}
43 changes: 43 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Test

on:
pull_request:
branches:
- main
schedule:
- cron: '0 22 * * 3'
workflow_call:

permissions:
contents: read

jobs:
test:
name: Test
strategy:
fail-fast: false
matrix:
node-version:
- '20.10'
- '18.18'
- '16.20'
os:
- macos-latest
- ubuntu-22.04
- windows-latest
runs-on: "${{ matrix.os }}"
steps:
- name: Install Linux Dependencies
if: ${{ matrix.os == 'ubuntu-22.04' }}
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y libasound2 libgtk-3-0 libnss3 libxss1 libxtst6 xvfb libgbm-dev
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: "${{ matrix.node-version }}"
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Test
run: yarn test
7 changes: 7 additions & 0 deletions .mocharc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
'watch-files': ['test/**/*.js', 'lib/**/*.js'],
recursive: true,
file: './test/mocha.setup.js', // setup file before everything else loads
'forbid-only': process.env.CI ?? false, // make sure no `test.only` is merged into `main`
reporter: 'spec',
};
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# @electron/asar - Electron Archive

[![CircleCI build status](https://circleci.com/gh/electron/asar/tree/main.svg?style=shield)](https://circleci.com/gh/electron/asar/tree/main)
[![Test](https://github.com/electron/asar/actions/workflows/test.yml/badge.svg)](https://github.com/electron/asar/actions/workflows/test.yml)
[![npm version](http://img.shields.io/npm/v/@electron/asar.svg)](https://npmjs.org/package/@electron/asar)

Asar is a simple extensive archive format, it works like `tar` that concatenates
@@ -116,10 +116,6 @@ await asar.createPackageWithOptions(src, dest, { transform: transform });
console.log('done.');
```

## Using with grunt

There is also an unofficial grunt plugin to generate asar archives at [bwin/grunt-asar][grunt-asar].

## Format

Asar uses [Pickle][pickle] to safely serialize binary value to file.
@@ -210,4 +206,3 @@ convert `Number` to UINT64.
* A integer value `blockSize` representing the size in bytes of each block in the `blocks` hashes above

[pickle]: https://chromium.googlesource.com/chromium/src/+/main/base/pickle.h
[grunt-asar]: https://github.com/bwin/grunt-asar
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -23,12 +23,17 @@
"bugs": {
"url": "https://github.com/electron/asar/issues"
},
"publishConfig": {
"provenance": true
},
"scripts": {
"build": "tsc",
"mocha": "xvfb-maybe electron-mocha --reporter spec && mocha --reporter spec",
"mocha": "xvfb-maybe electron-mocha && mocha",
"mocha:update": "mocha --update",
"mocha:watch": "mocha --watch",
"test": "yarn lint && yarn mocha",
"lint": "yarn prettier:check",
"prettier": "prettier \"src/**/*.ts\" \"test/**/*.ts\" \"test/**/*.js\"",
"prettier": "prettier \"src/**/*.ts\" \"test/**/*.js\" \"*.js\"",
"prettier:check": "yarn prettier --check",
"prettier:write": "yarn prettier --write",
"prepare": "tsc"
@@ -41,10 +46,12 @@
"devDependencies": {
"@types/minimatch": "^3.0.5",
"@types/node": "^12.0.0",
"chai": "^4.5.0",
"electron": "^22.0.0",
"electron-mocha": "^11.0.2",
"electron-mocha": "^13.0.1",
"lodash": "^4.17.15",
"mocha": "^10.1.0",
"mocha-chai-jest-snapshot": "^1.1.6",
"prettier": "^3.3.3",
"rimraf": "^3.0.2",
"typescript": "^5.5.4",
61 changes: 43 additions & 18 deletions src/asar.ts
Original file line number Diff line number Diff line change
@@ -26,7 +26,10 @@ function isUnpackedDir(dirPath: string, pattern: string, unpackDirs: string[]) {
}
return true;
} else {
return unpackDirs.some((unpackDir) => dirPath.startsWith(unpackDir));
return unpackDirs.some(
(unpackDir) =>
dirPath.startsWith(unpackDir) && !path.relative(unpackDir, dirPath).startsWith('..'),
);
}
}

@@ -37,6 +40,13 @@ export async function createPackage(src: string, dest: string) {
export type CreateOptions = {
dot?: boolean;
globOptions?: IOptions;
/**
* Path to a file containing the list of relative filepaths relative to `src` and the specific order they should be inserted into the asar.
* Formats allowed below:
* filepath
* : filepath
* <anything>:filepath
*/
ordering?: string;
pattern?: string;
transform?: (filePath: string) => NodeJS.ReadWriteStream | void;
@@ -77,7 +87,8 @@ export async function createPackageFromFiles(
});

const filesystem = new Filesystem(src);
const files: { filename: string; unpack: boolean }[] = [];
const files: disk.BasicFilesArray = [];
const links: disk.BasicFilesArray = [];
const unpackDirs: string[] = [];

let filenamesSorted: string[] = [];
@@ -137,37 +148,51 @@ export async function createPackageFromFiles(
}
const file = metadata[filename];

const shouldUnpackPath = function (
relativePath: string,
unpack: string | undefined,
unpackDir: string | undefined,
) {
let shouldUnpack = false;
if (unpack) {
shouldUnpack = minimatch(filename, unpack, { matchBase: true });
}
if (!shouldUnpack && unpackDir) {
shouldUnpack = isUnpackedDir(relativePath, unpackDir, unpackDirs);
}
return shouldUnpack;
};

let shouldUnpack: boolean;
switch (file.type) {
case 'directory':
if (options.unpackDir) {
shouldUnpack = isUnpackedDir(path.relative(src, filename), options.unpackDir, unpackDirs);
} else {
shouldUnpack = false;
}
shouldUnpack = shouldUnpackPath(path.relative(src, filename), undefined, options.unpackDir);
filesystem.insertDirectory(filename, shouldUnpack);
break;
case 'file':
shouldUnpack = false;
if (options.unpack) {
shouldUnpack = minimatch(filename, options.unpack, { matchBase: true });
}
if (!shouldUnpack && options.unpackDir) {
const dirName = path.relative(src, path.dirname(filename));
shouldUnpack = isUnpackedDir(dirName, options.unpackDir, unpackDirs);
}
files.push({ filename: filename, unpack: shouldUnpack });
shouldUnpack = shouldUnpackPath(
path.relative(src, path.dirname(filename)),
options.unpack,
options.unpackDir,
);
files.push({ filename, unpack: shouldUnpack });
return filesystem.insertFile(filename, shouldUnpack, file, options);
case 'link':
filesystem.insertLink(filename);
shouldUnpack = shouldUnpackPath(
path.relative(src, filename),
options.unpack,
options.unpackDir,
);
links.push({ filename, unpack: shouldUnpack });
filesystem.insertLink(filename, shouldUnpack);
break;
}
return Promise.resolve();
};

const insertsDone = async function () {
await fs.mkdirp(path.dirname(dest));
return disk.writeFilesystem(dest, filesystem, files, metadata);
return disk.writeFilesystem(dest, filesystem, { files, links }, metadata);
};

const names = filenamesSorted.slice();
10 changes: 8 additions & 2 deletions src/crawlfs.ts
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ import { glob as _glob } from 'glob';

import fs from './wrapped-fs';
import { Stats } from 'fs';
import * as path from 'path';
import { IOptions } from './types/glob';

const glob = promisify(_glob);
@@ -48,8 +49,13 @@ export async function crawl(dir: string, options: IOptions) {
// those appearing in archives we need to manually exclude theme here
const exactLinkIndex = links.findIndex((link) => filename === link);
return links.every((link, index) => {
if (index === exactLinkIndex) return true;
return !filename.startsWith(link);
if (index === exactLinkIndex) {
return true;
}
const isFileWithinSymlinkDir = filename.startsWith(link);
// symlink may point outside the directory: https://github.com/electron/asar/issues/303
const relativePath = path.relative(link, path.dirname(filename));
return !isFileWithinSymlinkDir || relativePath.startsWith('..');
});
});
return [filenames, metadata] as const;
28 changes: 24 additions & 4 deletions src/disk.ts
Original file line number Diff line number Diff line change
@@ -37,14 +37,17 @@ export type InputMetadata = {

export type BasicFilesArray = { filename: string; unpack: boolean }[];

export type FilesystemFilesAndLinks = { files: BasicFilesArray; links: BasicFilesArray };

const writeFileListToStream = async function (
dest: string,
filesystem: Filesystem,
out: NodeJS.WritableStream,
fileList: BasicFilesArray,
lists: FilesystemFilesAndLinks,
metadata: InputMetadata,
) {
for (const file of fileList) {
const { files, links } = lists;
for (const file of files) {
if (file.unpack) {
// the file should not be packed into archive
const filename = path.relative(filesystem.getRootPath(), file.filename);
@@ -53,13 +56,30 @@ const writeFileListToStream = async function (
await streamTransformedFile(file.filename, out, metadata[file.filename].transformed);
}
}
const unpackedSymlinks = links.filter((f) => f.unpack);
for (const file of unpackedSymlinks) {
// the symlink needs to be recreated outside in .unpacked
const filename = path.relative(filesystem.getRootPath(), file.filename);
const link = await fs.readlink(file.filename);
// if symlink is within subdirectories, then we need to recreate dir structure
await fs.mkdirp(path.join(`${dest}.unpacked`, path.dirname(filename)));
// create symlink within unpacked dir
await fs.symlink(link, path.join(`${dest}.unpacked`, filename)).catch(async (error) => {
if (error.code === 'EPERM' && error.syscall === 'symlink') {
throw new Error(
'Could not create symlinks for unpacked assets. On Windows, consider activating Developer Mode to allow non-admin users to create symlinks by following the instructions at https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development.',
);
}
throw error;
});
}
return out.end();
};

export async function writeFilesystem(
dest: string,
filesystem: Filesystem,
fileList: BasicFilesArray,
lists: FilesystemFilesAndLinks,
metadata: InputMetadata,
) {
const headerPickle = Pickle.createEmpty();
@@ -76,7 +96,7 @@ export async function writeFilesystem(
out.write(sizeBuf);
return out.write(headerBuf, () => resolve());
});
return writeFileListToStream(dest, filesystem, out, fileList, metadata);
return writeFileListToStream(dest, filesystem, out, lists, metadata);
}

export interface FileRecord extends FilesystemFileEntry {
Loading