refactor(adb): change sync push args to objects

This commit is contained in:
Simon Chan 2023-03-06 13:12:41 +08:00
parent 134e48d620
commit cde7923856
6 changed files with 96 additions and 57 deletions

View file

@ -570,18 +570,18 @@ class FileManagerState {
);
try {
await sync.write(
itemPath,
createFileStream(file).pipeThrough(
await sync.write({
filename: itemPath,
file: createFileStream(file).pipeThrough(
new ProgressStream(
action((uploaded) => {
this.uploadedSize = uploaded;
})
)
),
(LinuxFileType.File << 12) | 0o666,
file.lastModified / 1000
);
mode: (LinuxFileType.File << 12) | 0o666,
mtime: file.lastModified / 1000,
});
runInAction(() => {
this.uploadSpeed =

View file

@ -7,20 +7,39 @@ import { AdbSyncResponseId, adbSyncReadResponse } from "./response.js";
import type { AdbSyncSocket } from "./socket.js";
import { LinuxFileType } from "./stat.js";
export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024;
export interface AdbSyncPushV1Options {
socket: AdbSyncSocket;
filename: string;
file: ReadableStream<Uint8Array>;
mode?: number;
mtime?: number;
packetSize?: number;
}
export const AdbSyncPushV1DefaultOptions: {
[K in keyof AdbSyncPushV1Options as Pick<
AdbSyncPushV1Options,
K
> extends Required<Pick<AdbSyncPushV1Options, K>>
? never
: K]-?: Exclude<AdbSyncPushV1Options[K], undefined>;
} = {
mode: (LinuxFileType.File << 12) | 0o666,
mtime: (Date.now() / 1000) | 0,
packetSize: ADB_SYNC_MAX_PACKET_SIZE,
};
export const AdbSyncOkResponse = new Struct({ littleEndian: true }).uint32(
"unused"
);
export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024;
export async function adbSyncPushV1(
socket: AdbSyncSocket,
filename: string,
file: ReadableStream<Uint8Array>,
mode: number = (LinuxFileType.File << 12) | 0o666,
mtime: number = (Date.now() / 1000) | 0,
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE
) {
export async function adbSyncPushV1(options: AdbSyncPushV1Options) {
const { socket, filename, file, mode, mtime, packetSize } = {
...AdbSyncPushV1DefaultOptions,
...options,
};
const locked = await socket.lock();
try {
const pathAndMode = `${filename},${mode.toString()}`;
@ -66,28 +85,45 @@ export enum AdbSyncSendV2Flags {
DryRun = (1 << 31) >>> 0,
}
export interface AdbSyncPushV2Options extends AdbSyncPushV1Options {
dryRun?: boolean;
}
export const AdbSyncPushV2DefaultOptions: {
[K in keyof AdbSyncPushV2Options as Pick<
AdbSyncPushV2Options,
K
> extends Required<Pick<AdbSyncPushV2Options, K>>
? never
: K]-?: Exclude<AdbSyncPushV2Options[K], undefined>;
} = {
...AdbSyncPushV1DefaultOptions,
dryRun: false,
};
export const AdbSyncSendV2Request = new Struct({ littleEndian: true })
.uint32("id", placeholder<AdbSyncRequestId>())
.uint32("mode")
.uint32("flags", placeholder<AdbSyncSendV2Flags>());
export async function adbSyncPushV2(
socket: AdbSyncSocket,
filename: string,
file: ReadableStream<Uint8Array>,
mode: number = (LinuxFileType.File << 12) | 0o666,
mtime: number = (Date.now() / 1000) | 0,
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE
) {
export async function adbSyncPushV2(options: AdbSyncPushV2Options) {
const { socket, filename, file, mode, mtime, packetSize, dryRun } = {
...AdbSyncPushV2DefaultOptions,
...options,
};
const locked = await socket.lock();
try {
await adbSyncWriteRequest(locked, AdbSyncRequestId.SendV2, filename);
let flags: AdbSyncSendV2Flags = AdbSyncSendV2Flags.None;
if (dryRun) {
flags |= AdbSyncSendV2Flags.DryRun;
}
await locked.write(
AdbSyncSendV2Request.serialize({
id: AdbSyncRequestId.SendV2,
mode,
flags: 0,
flags,
})
);
@ -114,18 +150,16 @@ export async function adbSyncPushV2(
}
}
export function adbSyncPush(
v2: boolean,
socket: AdbSyncSocket,
filename: string,
file: ReadableStream<Uint8Array>,
mode: number = (LinuxFileType.File << 12) | 0o666,
mtime: number = (Date.now() / 1000) | 0,
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE
) {
if (v2) {
return adbSyncPushV2(socket, filename, file, mode, mtime, packetSize);
export interface AdbSyncPushOptions extends AdbSyncPushV2Options {
v2: boolean;
}
export function adbSyncPush(options: AdbSyncPushOptions) {
if (options.v2) {
return adbSyncPushV2(options);
} else if (options.dryRun) {
throw new Error("dryRun is not supported in v1");
} else {
return adbSyncPushV1(socket, filename, file, mode, mtime, packetSize);
return adbSyncPushV1(options);
}
}

View file

@ -29,6 +29,13 @@ export function dirname(path: string): string {
return path.substring(0, end);
}
export interface AdbSyncWriteOptions {
filename: string;
file: ReadableStream<Uint8Array>;
mode?: number;
mtime?: number;
}
export class AdbSync extends AutoDisposable {
protected _adb: Adb;
protected _socket: AdbSyncSocket;
@ -129,12 +136,7 @@ export class AdbSync extends AutoDisposable {
* @param mtime The modified time of the file.
* @returns A `WritableStream` that writes to the file.
*/
public async write(
filename: string,
file: ReadableStream<Uint8Array>,
mode?: number,
mtime?: number
) {
public async write(options: AdbSyncWriteOptions) {
if (this.needPushMkdirWorkaround) {
// It may fail if the path is already existed.
// Ignore the result.
@ -142,18 +144,15 @@ export class AdbSync extends AutoDisposable {
await this._adb.subprocess.spawnAndWait([
"mkdir",
"-p",
escapeArg(dirname(filename)),
escapeArg(dirname(options.filename)),
]);
}
await adbSyncPush(
this.supportsSendReceiveV2,
this._socket,
filename,
file,
mode,
mtime
);
await adbSyncPush({
v2: this.supportsSendReceiveV2,
socket: this._socket,
...options,
});
}
public override async dispose() {

View file

@ -233,7 +233,10 @@ export class PackageManager extends AdbCommandBase {
const filePath = `/data/local/tmp/${fileName}.apk`;
try {
await sync.write(filePath, stream);
await sync.write({
filename: filePath,
file: stream,
});
} finally {
await sync.dispose();
}

View file

@ -98,11 +98,14 @@ export class AdbScrcpyClient {
public static async pushServer(
adb: Adb,
file: ReadableStream<Uint8Array>,
path = DEFAULT_SERVER_PATH
filename = DEFAULT_SERVER_PATH
) {
const sync = await adb.sync();
try {
await sync.write(path, file);
await sync.write({
filename: filename,
file,
});
} finally {
await sync.dispose();
}

View file

@ -65,8 +65,8 @@ export interface ScrcpyVideoStreamConfigurationPacket {
export interface ScrcpyVideoStreamFramePacket {
type: "frame";
keyframe?: boolean | undefined;
pts?: bigint | undefined;
keyframe?: boolean;
pts?: bigint;
data: Uint8Array;
}