@yume-chan/adb 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +18 -0
- package/CHANGELOG.md +13 -1
- package/LICENSE +1 -1
- package/esm/adb.d.ts +13 -8
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +63 -38
- package/esm/adb.js.map +1 -1
- package/esm/auth.d.ts +4 -4
- package/esm/auth.d.ts.map +1 -1
- package/esm/auth.js +6 -6
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +3 -3
- package/esm/backend.d.ts.map +1 -1
- package/esm/commands/base.d.ts +2 -2
- package/esm/commands/base.d.ts.map +1 -1
- package/esm/commands/base.js +1 -1
- package/esm/commands/base.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +22 -6
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +33 -45
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/install.d.ts +2 -2
- package/esm/commands/install.d.ts.map +1 -1
- package/esm/commands/install.js +12 -5
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts.map +1 -1
- package/esm/commands/power.js +13 -9
- package/esm/commands/power.js.map +1 -1
- package/esm/commands/reverse.d.ts +5 -5
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +20 -18
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +52 -0
- package/esm/commands/subprocess/command.d.ts.map +1 -0
- package/esm/commands/subprocess/command.js +81 -0
- package/esm/commands/subprocess/command.js.map +1 -0
- package/esm/commands/subprocess/index.d.ts +1 -53
- package/esm/commands/subprocess/index.d.ts.map +1 -1
- package/esm/commands/subprocess/index.js +1 -85
- package/esm/commands/subprocess/index.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +5 -5
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +5 -3
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +4 -4
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +28 -20
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +7 -7
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/sync/index.d.ts +1 -1
- package/esm/commands/sync/index.d.ts.map +1 -1
- package/esm/commands/sync/index.js +1 -1
- package/esm/commands/sync/index.js.map +1 -1
- package/esm/commands/sync/list.d.ts +7 -7
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +34 -50
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +5 -4
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +21 -22
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +4 -4
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +7 -11
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +4 -4
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +6 -6
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +5 -10
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +35 -26
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/stat.d.ts +7 -7
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +48 -55
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +7 -7
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +25 -22
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/crypto.d.ts.map +1 -1
- package/esm/crypto.js +26 -16
- package/esm/crypto.js.map +1 -1
- package/esm/index.d.ts +9 -10
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +9 -10
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +8 -8
- package/esm/packet.d.ts.map +1 -1
- package/esm/packet.js +14 -12
- package/esm/packet.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +11 -6
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +28 -20
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +1 -1
- package/esm/socket/index.d.ts.map +1 -1
- package/esm/socket/index.js +1 -1
- package/esm/socket/index.js.map +1 -1
- package/esm/socket/socket.d.ts +5 -5
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +37 -17
- package/esm/socket/socket.js.map +1 -1
- package/esm/utils/auto-reset-event.d.ts +1 -1
- package/esm/utils/auto-reset-event.d.ts.map +1 -1
- package/esm/utils/auto-reset-event.js +2 -2
- package/esm/utils/base64.d.ts +23 -0
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +36 -29
- package/esm/utils/base64.js.map +1 -1
- package/package.json +19 -17
- package/src/adb.ts +140 -86
- package/src/auth.ts +27 -18
- package/src/backend.ts +7 -4
- package/src/commands/base.ts +3 -2
- package/src/commands/framebuffer.ts +48 -47
- package/src/commands/install.ts +20 -10
- package/src/commands/power.ts +14 -10
- package/src/commands/reverse.ts +53 -33
- package/src/commands/subprocess/command.ts +134 -0
- package/src/commands/subprocess/index.ts +1 -137
- package/src/commands/subprocess/protocols/none.ts +10 -6
- package/src/commands/subprocess/protocols/shell.ts +72 -39
- package/src/commands/subprocess/protocols/types.ts +12 -8
- package/src/commands/sync/index.ts +1 -1
- package/src/commands/sync/list.ts +63 -68
- package/src/commands/sync/pull.ts +53 -37
- package/src/commands/sync/push.ts +26 -15
- package/src/commands/sync/request.ts +20 -21
- package/src/commands/sync/response.ts +63 -53
- package/src/commands/sync/stat.ts +91 -90
- package/src/commands/sync/sync.ts +56 -34
- package/src/crypto.ts +61 -33
- package/src/features.ts +1 -1
- package/src/index.ts +9 -11
- package/src/packet.ts +40 -30
- package/src/socket/dispatcher.ts +119 -77
- package/src/socket/index.ts +1 -1
- package/src/socket/socket.ts +68 -26
- package/src/utils/auto-reset-event.ts +3 -3
- package/src/utils/base64.ts +75 -42
- package/tsconfig.build.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/stream/buffered.d.ts +0 -39
- package/esm/stream/buffered.d.ts.map +0 -1
- package/esm/stream/buffered.js +0 -143
- package/esm/stream/buffered.js.map +0 -1
- package/esm/stream/detect.d.ts +0 -2
- package/esm/stream/detect.d.ts.map +0 -1
- package/esm/stream/detect.js +0 -6
- package/esm/stream/detect.js.map +0 -1
- package/esm/stream/detect.native.d.ts +0 -240
- package/esm/stream/detect.native.d.ts.map +0 -1
- package/esm/stream/detect.native.js +0 -60
- package/esm/stream/detect.native.js.map +0 -1
- package/esm/stream/detect.polyfill.d.ts +0 -18
- package/esm/stream/detect.polyfill.d.ts.map +0 -1
- package/esm/stream/detect.polyfill.js +0 -4
- package/esm/stream/detect.polyfill.js.map +0 -1
- package/esm/stream/index.d.ts +0 -4
- package/esm/stream/index.d.ts.map +0 -1
- package/esm/stream/index.js +0 -4
- package/esm/stream/index.js.map +0 -1
- package/esm/stream/transform.d.ts +0 -124
- package/esm/stream/transform.d.ts.map +0 -1
- package/esm/stream/transform.js +0 -379
- package/esm/stream/transform.js.map +0 -1
- package/src/stream/buffered.ts +0 -168
- package/src/stream/detect.native.ts +0 -362
- package/src/stream/detect.polyfill.ts +0 -22
- package/src/stream/detect.ts +0 -7
- package/src/stream/index.ts +0 -3
- package/src/stream/transform.ts +0 -474
- package/tsconfig.test.json +0 -9
- package/web-streams-polyfill-4.0.0-beta.2.tgz +0 -0
|
@@ -1,64 +1,74 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { type BufferedReadableStream } from "@yume-chan/stream-extra";
|
|
2
|
+
import Struct, {
|
|
3
|
+
type StructLike,
|
|
4
|
+
type StructValueType,
|
|
5
|
+
} from "@yume-chan/struct";
|
|
6
|
+
|
|
3
7
|
import { decodeUtf8 } from "../../utils/index.js";
|
|
4
8
|
|
|
5
9
|
export enum AdbSyncResponseId {
|
|
6
|
-
Entry =
|
|
7
|
-
Entry2 =
|
|
8
|
-
Lstat =
|
|
9
|
-
Stat =
|
|
10
|
-
Lstat2 =
|
|
11
|
-
Done =
|
|
12
|
-
Data =
|
|
13
|
-
Ok =
|
|
14
|
-
Fail =
|
|
10
|
+
Entry = "DENT",
|
|
11
|
+
Entry2 = "DNT2",
|
|
12
|
+
Lstat = "STAT",
|
|
13
|
+
Stat = "STA2",
|
|
14
|
+
Lstat2 = "LST2",
|
|
15
|
+
Done = "DONE",
|
|
16
|
+
Data = "DATA",
|
|
17
|
+
Ok = "OKAY",
|
|
18
|
+
Fail = "FAIL",
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
public readonly id = AdbSyncResponseId.Done;
|
|
21
|
+
export const AdbSyncFailResponse = new Struct({ littleEndian: true })
|
|
22
|
+
.uint32("messageLength")
|
|
23
|
+
.string("message", { lengthField: "messageLength" })
|
|
24
|
+
.postDeserialize((object) => {
|
|
25
|
+
throw new Error(object.message);
|
|
26
|
+
});
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
export async function adbSyncReadResponse<T>(
|
|
29
|
+
stream: BufferedReadableStream,
|
|
30
|
+
id: AdbSyncResponseId,
|
|
31
|
+
type: StructLike<T>
|
|
32
|
+
): Promise<T> {
|
|
33
|
+
const actualId = decodeUtf8(await stream.read(4));
|
|
34
|
+
switch (actualId) {
|
|
35
|
+
case AdbSyncResponseId.Fail:
|
|
36
|
+
await AdbSyncFailResponse.deserialize(stream);
|
|
37
|
+
throw new Error("Unreachable");
|
|
38
|
+
case id:
|
|
39
|
+
return await type.deserialize(stream);
|
|
40
|
+
default:
|
|
41
|
+
throw new Error(`Expected '${id}', but got '${actualId}'`);
|
|
33
42
|
}
|
|
34
43
|
}
|
|
35
44
|
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
45
|
+
export async function* adbSyncReadResponses<
|
|
46
|
+
T extends Struct<object, PropertyKey, object, any>
|
|
47
|
+
>(
|
|
48
|
+
stream: BufferedReadableStream,
|
|
49
|
+
id: AdbSyncResponseId,
|
|
50
|
+
type: T
|
|
51
|
+
): AsyncGenerator<StructValueType<T>, void, void> {
|
|
52
|
+
while (true) {
|
|
53
|
+
const actualId = decodeUtf8(await stream.read(4));
|
|
54
|
+
switch (actualId) {
|
|
55
|
+
case AdbSyncResponseId.Fail:
|
|
56
|
+
await AdbSyncFailResponse.deserialize(stream);
|
|
57
|
+
throw new Error("Unreachable");
|
|
58
|
+
case AdbSyncResponseId.Done:
|
|
59
|
+
// `DONE` responses' size are always same as the request's normal response.
|
|
60
|
+
//
|
|
61
|
+
// For example, `DONE` responses for `LIST` requests are 16 bytes (same as `DENT` responses),
|
|
62
|
+
// but `DONE` responses for `STAT` requests are 12 bytes (same as `STAT` responses).
|
|
63
|
+
await stream.read(type.size);
|
|
64
|
+
return;
|
|
65
|
+
case id:
|
|
66
|
+
yield await type.deserialize(stream);
|
|
67
|
+
break;
|
|
68
|
+
default:
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Expected '${id}' or '${AdbSyncResponseId.Done}', but got '${actualId}'`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
61
73
|
}
|
|
62
|
-
|
|
63
|
-
throw new Error(`Expected '${Object.keys(types).join(', ')}', but got '${id}'`);
|
|
64
74
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
type BufferedReadableStream,
|
|
3
|
+
type WritableStreamDefaultWriter,
|
|
4
|
+
} from "@yume-chan/stream-extra";
|
|
5
|
+
import Struct, { placeholder } from "@yume-chan/struct";
|
|
6
|
+
|
|
7
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
|
|
8
|
+
import { AdbSyncResponseId, adbSyncReadResponse } from "./response.js";
|
|
5
9
|
|
|
6
10
|
// https://github.com/python/cpython/blob/4e581d64b8aff3e2eda99b12f080c877bb78dfca/Lib/stat.py#L36
|
|
7
11
|
export enum LinuxFileType {
|
|
@@ -23,27 +27,27 @@ export interface AdbSyncStat {
|
|
|
23
27
|
ctime?: bigint;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
export const AdbSyncLstatResponse =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
30
|
+
export const AdbSyncLstatResponse = new Struct({ littleEndian: true })
|
|
31
|
+
.int32("mode")
|
|
32
|
+
.int32("size")
|
|
33
|
+
.int32("mtime")
|
|
34
|
+
.extra({
|
|
35
|
+
id: AdbSyncResponseId.Lstat as const,
|
|
36
|
+
get type() {
|
|
37
|
+
return (this.mode >> 12) as LinuxFileType;
|
|
38
|
+
},
|
|
39
|
+
get permission() {
|
|
40
|
+
return this.mode & 0b00001111_11111111;
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
.postDeserialize((object) => {
|
|
44
|
+
if (object.mode === 0 && object.size === 0 && object.mtime === 0) {
|
|
45
|
+
throw new Error("lstat error");
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export type AdbSyncLstatResponse =
|
|
50
|
+
typeof AdbSyncLstatResponse["TDeserializeResult"];
|
|
47
51
|
|
|
48
52
|
export enum AdbSyncStatErrorCode {
|
|
49
53
|
SUCCESS = 0,
|
|
@@ -69,83 +73,80 @@ export enum AdbSyncStatErrorCode {
|
|
|
69
73
|
ETXTBSY = 26,
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
export const AdbSyncStatResponse =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const LSTAT_RESPONSE_TYPES = {
|
|
103
|
-
[AdbSyncResponseId.Lstat]: AdbSyncLstatResponse,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const LSTAT_V2_RESPONSE_TYPES = {
|
|
107
|
-
[AdbSyncResponseId.Lstat2]: AdbSyncStatResponse,
|
|
108
|
-
};
|
|
76
|
+
export const AdbSyncStatResponse = new Struct({ littleEndian: true })
|
|
77
|
+
.uint32("error", placeholder<AdbSyncStatErrorCode>())
|
|
78
|
+
.uint64("dev")
|
|
79
|
+
.uint64("ino")
|
|
80
|
+
.uint32("mode")
|
|
81
|
+
.uint32("nlink")
|
|
82
|
+
.uint32("uid")
|
|
83
|
+
.uint32("gid")
|
|
84
|
+
.uint64("size")
|
|
85
|
+
.uint64("atime")
|
|
86
|
+
.uint64("mtime")
|
|
87
|
+
.uint64("ctime")
|
|
88
|
+
.extra({
|
|
89
|
+
id: AdbSyncResponseId.Stat as const,
|
|
90
|
+
get type() {
|
|
91
|
+
return (this.mode >> 12) as LinuxFileType;
|
|
92
|
+
},
|
|
93
|
+
get permission() {
|
|
94
|
+
return this.mode & 0b00001111_11111111;
|
|
95
|
+
},
|
|
96
|
+
})
|
|
97
|
+
.postDeserialize((object) => {
|
|
98
|
+
if (object.error) {
|
|
99
|
+
throw new Error(AdbSyncStatErrorCode[object.error]);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export type AdbSyncStatResponse =
|
|
104
|
+
typeof AdbSyncStatResponse["TDeserializeResult"];
|
|
109
105
|
|
|
110
106
|
export async function adbSyncLstat(
|
|
111
|
-
stream:
|
|
107
|
+
stream: BufferedReadableStream,
|
|
112
108
|
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
113
109
|
path: string,
|
|
114
|
-
v2: boolean
|
|
110
|
+
v2: boolean
|
|
115
111
|
): Promise<AdbSyncStat> {
|
|
116
|
-
let requestId: AdbSyncRequestId.Lstat | AdbSyncRequestId.Lstat2;
|
|
117
|
-
let responseType: typeof LSTAT_RESPONSE_TYPES | typeof LSTAT_V2_RESPONSE_TYPES;
|
|
118
|
-
|
|
119
112
|
if (v2) {
|
|
120
|
-
|
|
121
|
-
|
|
113
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Lstat2, path);
|
|
114
|
+
return await adbSyncReadResponse(
|
|
115
|
+
stream,
|
|
116
|
+
AdbSyncResponseId.Lstat2,
|
|
117
|
+
AdbSyncStatResponse
|
|
118
|
+
);
|
|
122
119
|
} else {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
120
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Lstat, path);
|
|
121
|
+
const response = await adbSyncReadResponse(
|
|
122
|
+
stream,
|
|
123
|
+
AdbSyncResponseId.Lstat,
|
|
124
|
+
AdbSyncLstatResponse
|
|
125
|
+
);
|
|
126
|
+
return {
|
|
127
|
+
mode: response.mode,
|
|
128
|
+
// Convert to `BigInt` to make it compatible with `AdbSyncStatResponse`
|
|
129
|
+
size: BigInt(response.size),
|
|
130
|
+
mtime: BigInt(response.mtime),
|
|
131
|
+
get type() {
|
|
132
|
+
return response.type;
|
|
133
|
+
},
|
|
134
|
+
get permission() {
|
|
135
|
+
return response.permission;
|
|
136
|
+
},
|
|
137
|
+
};
|
|
141
138
|
}
|
|
142
139
|
}
|
|
143
140
|
|
|
144
141
|
export async function adbSyncStat(
|
|
145
|
-
stream:
|
|
142
|
+
stream: BufferedReadableStream,
|
|
146
143
|
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
147
|
-
path: string
|
|
144
|
+
path: string
|
|
148
145
|
): Promise<AdbSyncStatResponse> {
|
|
149
146
|
await adbSyncWriteRequest(writer, AdbSyncRequestId.Stat, path);
|
|
150
|
-
return await adbSyncReadResponse(
|
|
147
|
+
return await adbSyncReadResponse(
|
|
148
|
+
stream,
|
|
149
|
+
AdbSyncResponseId.Stat,
|
|
150
|
+
AdbSyncStatResponse
|
|
151
|
+
);
|
|
151
152
|
}
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import { AutoDisposable } from
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {
|
|
1
|
+
import { AutoDisposable } from "@yume-chan/event";
|
|
2
|
+
import {
|
|
3
|
+
BufferedReadableStream,
|
|
4
|
+
WrapReadableStream,
|
|
5
|
+
WrapWritableStream,
|
|
6
|
+
type ReadableStream,
|
|
7
|
+
type WritableStream,
|
|
8
|
+
type WritableStreamDefaultWriter,
|
|
9
|
+
} from "@yume-chan/stream-extra";
|
|
10
|
+
|
|
11
|
+
import { type Adb } from "../../adb.js";
|
|
12
|
+
import { AdbFeatures } from "../../features.js";
|
|
13
|
+
import { type AdbSocket } from "../../socket/index.js";
|
|
14
|
+
import { AutoResetEvent } from "../../utils/index.js";
|
|
15
|
+
import { escapeArg } from "../subprocess/index.js";
|
|
16
|
+
|
|
17
|
+
import { adbSyncOpenDir, type AdbSyncEntry } from "./list.js";
|
|
18
|
+
import { adbSyncPull } from "./pull.js";
|
|
19
|
+
import { adbSyncPush } from "./push.js";
|
|
20
|
+
import { adbSyncLstat, adbSyncStat } from "./stat.js";
|
|
12
21
|
|
|
13
22
|
/**
|
|
14
23
|
* A simplified `dirname` function that only handles absolute unix paths.
|
|
@@ -16,12 +25,12 @@ import { adbSyncLstat, adbSyncStat } from './stat.js';
|
|
|
16
25
|
* @returns the directory name of the input path
|
|
17
26
|
*/
|
|
18
27
|
export function dirname(path: string): string {
|
|
19
|
-
const end = path.lastIndexOf(
|
|
28
|
+
const end = path.lastIndexOf("/");
|
|
20
29
|
if (end === -1) {
|
|
21
30
|
throw new Error(`Invalid path`);
|
|
22
31
|
}
|
|
23
32
|
if (end === 0) {
|
|
24
|
-
return
|
|
33
|
+
return "/";
|
|
25
34
|
}
|
|
26
35
|
return path.substring(0, end);
|
|
27
36
|
}
|
|
@@ -29,34 +38,38 @@ export function dirname(path: string): string {
|
|
|
29
38
|
export class AdbSync extends AutoDisposable {
|
|
30
39
|
protected adb: Adb;
|
|
31
40
|
|
|
32
|
-
protected stream:
|
|
33
|
-
|
|
41
|
+
protected stream: BufferedReadableStream;
|
|
42
|
+
// Getting another writer on a locked WritableStream will throw.
|
|
43
|
+
// We don't want this behavior on higher-level APIs.
|
|
44
|
+
// So we acquire the writer early and use a blocking lock to guard it.
|
|
34
45
|
protected writer: WritableStreamDefaultWriter<Uint8Array>;
|
|
35
|
-
|
|
36
46
|
protected sendLock = this.addDisposable(new AutoResetEvent());
|
|
37
47
|
|
|
38
48
|
public get supportsStat(): boolean {
|
|
39
|
-
return this.adb.features
|
|
49
|
+
return this.adb.features.includes(AdbFeatures.StatV2);
|
|
40
50
|
}
|
|
41
51
|
|
|
42
52
|
public get supportsList2(): boolean {
|
|
43
|
-
return this.adb.features
|
|
53
|
+
return this.adb.features.includes(AdbFeatures.ListV2);
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
public get fixedPushMkdir(): boolean {
|
|
47
|
-
return this.adb.features
|
|
57
|
+
return this.adb.features.includes(AdbFeatures.FixedPushMkdir);
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
public get needPushMkdirWorkaround(): boolean {
|
|
51
61
|
// https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
|
|
52
|
-
return
|
|
62
|
+
return (
|
|
63
|
+
this.adb.features.includes(AdbFeatures.ShellV2) &&
|
|
64
|
+
!this.fixedPushMkdir
|
|
65
|
+
);
|
|
53
66
|
}
|
|
54
67
|
|
|
55
68
|
public constructor(adb: Adb, socket: AdbSocket) {
|
|
56
69
|
super();
|
|
57
70
|
|
|
58
71
|
this.adb = adb;
|
|
59
|
-
this.stream = new
|
|
72
|
+
this.stream = new BufferedReadableStream(socket.readable);
|
|
60
73
|
this.writer = socket.writable.getWriter();
|
|
61
74
|
}
|
|
62
75
|
|
|
@@ -64,7 +77,12 @@ export class AdbSync extends AutoDisposable {
|
|
|
64
77
|
await this.sendLock.wait();
|
|
65
78
|
|
|
66
79
|
try {
|
|
67
|
-
return adbSyncLstat(
|
|
80
|
+
return adbSyncLstat(
|
|
81
|
+
this.stream,
|
|
82
|
+
this.writer,
|
|
83
|
+
path,
|
|
84
|
+
this.supportsStat
|
|
85
|
+
);
|
|
68
86
|
} finally {
|
|
69
87
|
this.sendLock.notify();
|
|
70
88
|
}
|
|
@@ -72,7 +90,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
72
90
|
|
|
73
91
|
public async stat(path: string) {
|
|
74
92
|
if (!this.supportsStat) {
|
|
75
|
-
throw new Error(
|
|
93
|
+
throw new Error("Not supported");
|
|
76
94
|
}
|
|
77
95
|
|
|
78
96
|
await this.sendLock.wait();
|
|
@@ -86,7 +104,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
86
104
|
|
|
87
105
|
public async isDirectory(path: string): Promise<boolean> {
|
|
88
106
|
try {
|
|
89
|
-
await this.lstat(path +
|
|
107
|
+
await this.lstat(path + "/");
|
|
90
108
|
return true;
|
|
91
109
|
} catch (e) {
|
|
92
110
|
return false;
|
|
@@ -99,7 +117,12 @@ export class AdbSync extends AutoDisposable {
|
|
|
99
117
|
await this.sendLock.wait();
|
|
100
118
|
|
|
101
119
|
try {
|
|
102
|
-
yield* adbSyncOpenDir(
|
|
120
|
+
yield* adbSyncOpenDir(
|
|
121
|
+
this.stream,
|
|
122
|
+
this.writer,
|
|
123
|
+
path,
|
|
124
|
+
this.supportsList2
|
|
125
|
+
);
|
|
103
126
|
} finally {
|
|
104
127
|
this.sendLock.notify();
|
|
105
128
|
}
|
|
@@ -125,7 +148,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
125
148
|
await this.sendLock.wait();
|
|
126
149
|
return adbSyncPull(this.stream, this.writer, filename);
|
|
127
150
|
},
|
|
128
|
-
close:
|
|
151
|
+
close: () => {
|
|
129
152
|
this.sendLock.notify();
|
|
130
153
|
},
|
|
131
154
|
});
|
|
@@ -142,7 +165,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
142
165
|
public write(
|
|
143
166
|
filename: string,
|
|
144
167
|
mode?: number,
|
|
145
|
-
mtime?: number
|
|
168
|
+
mtime?: number
|
|
146
169
|
): WritableStream<Uint8Array> {
|
|
147
170
|
return new WrapWritableStream({
|
|
148
171
|
start: async () => {
|
|
@@ -151,10 +174,10 @@ export class AdbSync extends AutoDisposable {
|
|
|
151
174
|
if (this.needPushMkdirWorkaround) {
|
|
152
175
|
// It may fail if the path is already existed.
|
|
153
176
|
// Ignore the result.
|
|
154
|
-
// TODO: sync: test
|
|
177
|
+
// TODO: sync: test push mkdir workaround (need an Android 8 device)
|
|
155
178
|
await this.adb.subprocess.spawnAndWait([
|
|
156
|
-
|
|
157
|
-
|
|
179
|
+
"mkdir",
|
|
180
|
+
"-p",
|
|
158
181
|
escapeArg(dirname(filename)),
|
|
159
182
|
]);
|
|
160
183
|
}
|
|
@@ -164,18 +187,17 @@ export class AdbSync extends AutoDisposable {
|
|
|
164
187
|
this.writer,
|
|
165
188
|
filename,
|
|
166
189
|
mode,
|
|
167
|
-
mtime
|
|
190
|
+
mtime
|
|
168
191
|
);
|
|
169
192
|
},
|
|
170
|
-
close:
|
|
193
|
+
close: () => {
|
|
171
194
|
this.sendLock.notify();
|
|
172
|
-
}
|
|
195
|
+
},
|
|
173
196
|
});
|
|
174
197
|
}
|
|
175
198
|
|
|
176
199
|
public override async dispose() {
|
|
177
200
|
super.dispose();
|
|
178
|
-
await this.stream.close();
|
|
179
201
|
await this.writer.close();
|
|
180
202
|
}
|
|
181
203
|
}
|