@team-agent/installer 0.5.100 → 0.5.102
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/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/src/cli/diagnose.rs +29 -7
- package/crates/team-agent/src/cli/mod.rs +24 -8
- package/crates/team-agent/src/cli/tests/main_preserved.rs +0 -74
- package/crates/team-agent/src/compiler/tests.rs +20 -23
- package/crates/team-agent/src/compiler.rs +52 -65
- package/crates/team-agent/src/coordinator/tests/s3_bounded.rs +16 -48
- package/crates/team-agent/src/leader/start.rs +1 -14
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +211 -16
- package/crates/team-agent/src/lifecycle/launch/clone_agent.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +15 -5
- package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +89 -6
- package/crates/team-agent/src/lifecycle/launch/role_source.rs +168 -32
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch.rs +11 -3
- package/crates/team-agent/src/lifecycle/profile_launch.rs +23 -8
- package/crates/team-agent/src/lifecycle/restart/agent.rs +2 -2
- package/crates/team-agent/src/lifecycle/restart/avatar.rs +1806 -0
- package/crates/team-agent/src/lifecycle/restart/common.rs +115 -2
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +8 -2
- package/crates/team-agent/src/lifecycle/restart/selection.rs +14 -2
- package/crates/team-agent/src/lifecycle/restart.rs +11 -4
- package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +0 -28
- package/crates/team-agent/src/lifecycle/tests/pi_compiler_red.rs +11 -9
- package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +8 -401
- package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/pi_fork_session_inheritance_red.rs +1398 -0
- package/crates/team-agent/src/lifecycle/tests.rs +1 -0
- package/crates/team-agent/src/lifecycle/types.rs +10 -2
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +22 -8
- package/crates/team-agent/src/mcp_server/helpers.rs +0 -16
- package/crates/team-agent/src/mcp_server/lifecycle_tools/mod.rs +2 -7
- package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +1 -127
- package/crates/team-agent/src/mcp_server/mod.rs +7 -12
- package/crates/team-agent/src/mcp_server/tests/scoped.rs +1 -132
- package/crates/team-agent/src/mcp_server/tests/send.rs +1 -93
- package/crates/team-agent/src/mcp_server/tests/tools.rs +0 -61
- package/crates/team-agent/src/mcp_server/tests/wire.rs +6 -51
- package/crates/team-agent/src/mcp_server/tests.rs +4 -200
- package/crates/team-agent/src/mcp_server/tools.rs +5 -396
- package/crates/team-agent/src/mcp_server/types.rs +3 -36
- package/crates/team-agent/src/mcp_server/wire.rs +2 -223
- package/crates/team-agent/src/messaging/leader_receiver.rs +1 -1
- package/crates/team-agent/src/messaging/mod.rs +2 -2
- package/crates/team-agent/src/messaging/scheduler.rs +2 -205
- package/crates/team-agent/src/messaging/tests/basic.rs +0 -31
- package/crates/team-agent/src/messaging/tests/main_preserved.rs +0 -73
- package/crates/team-agent/src/messaging/tests/runtime.rs +0 -26
- package/crates/team-agent/src/messaging/types.rs +0 -20
- package/crates/team-agent/src/model/spec.rs +15 -18
- package/crates/team-agent/src/provider/types.rs +2 -0
- package/crates/team-agent/src/state/persist.rs +58 -2
- package/crates/team-agent/src/state/projection.rs +5 -1
- package/crates/team-agent/src/state/repository/tests.rs +1 -16
- package/crates/team-agent/src/state/repository.rs +126 -37
- package/crates/team-agent/src/transport/test_support.rs +23 -3
- package/package.json +4 -4
- package/skills/team-agent/SKILL.md +18 -47
- package/skills/team-agent/command-coverage.json +7 -0
- package/skills/team-agent/references/team-agent-operator.md +28 -118
- package/skills/team-agent/references/team-in-team.md +4 -19
- package/crates/team-agent/src/mcp_server/lifecycle_tools/agent_ops.rs +0 -484
|
@@ -290,67 +290,6 @@
|
|
|
290
290
|
);
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
// ════════════════════════════════════════════════════════════════════════
|
|
294
|
-
// CONTROL-PLANE: request_human creates a requires_ack leader message → needs_human
|
|
295
|
-
// (tools.py:342-346). sender = explicit > env > "unknown" (never leader).
|
|
296
|
-
//
|
|
297
|
-
// Post-#230 N31/N32 funnel (cr-approved I-3): request_human routes through the
|
|
298
|
-
// shared leader-delivery primitive (`send_to_leader_receiver`) instead of doing a
|
|
299
|
-
// raw `store.create_message` bypass. Return shape from the caller's perspective is
|
|
300
|
-
// unchanged: `status="needs_human"` + a populated `message_id`. With no leader
|
|
301
|
-
// pane bound in this fixture, the primitive's I-4 rebind_required path STILL
|
|
302
|
-
// persists the message row and returns its `message_id` — audit + rebind replay
|
|
303
|
-
// both depend on it.
|
|
304
|
-
// ════════════════════════════════════════════════════════════════════════
|
|
305
|
-
#[test]
|
|
306
|
-
fn request_human_returns_needs_human_with_message_id() {
|
|
307
|
-
let tools = TeamOrchestratorTools::with_identity(
|
|
308
|
-
&unique_ws("request-human"),
|
|
309
|
-
Some(AgentId::new("worker-3")),
|
|
310
|
-
Some(TeamKey::new("teamA")),
|
|
311
|
-
);
|
|
312
|
-
let ok = tools.request_human("need approval", Some("task-1"), None)
|
|
313
|
-
.expect("request_human ok");
|
|
314
|
-
let v = serde_json::to_value(&ok).unwrap();
|
|
315
|
-
assert_eq!(v.get("status"), Some(&json!("needs_human")));
|
|
316
|
-
assert!(v.get("message_id").and_then(Value::as_str).is_some(),
|
|
317
|
-
"request_human must return the created leader message_id (persisted for rebind audit even on I-4 rebind_required)");
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// ════════════════════════════════════════════════════════════════════════
|
|
321
|
-
// CONTROL-PLANE: update_state appends a note + returns state_file (tools.py:316-325)
|
|
322
|
-
// ════════════════════════════════════════════════════════════════════════
|
|
323
|
-
#[test]
|
|
324
|
-
fn update_state_returns_ok_and_state_file_path() {
|
|
325
|
-
let ws = seed_state_ws(
|
|
326
|
-
"update-state",
|
|
327
|
-
&json!({
|
|
328
|
-
"active_team_key": "teamA",
|
|
329
|
-
"team_key": "teamA",
|
|
330
|
-
"session_name": "teamA",
|
|
331
|
-
"status": "alive",
|
|
332
|
-
"teams": {
|
|
333
|
-
"teamA": {
|
|
334
|
-
"team_key": "teamA",
|
|
335
|
-
"session_name": "teamA",
|
|
336
|
-
"status": "alive",
|
|
337
|
-
"agents": {}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}),
|
|
341
|
-
);
|
|
342
|
-
let tools = TeamOrchestratorTools::with_identity(
|
|
343
|
-
&ws,
|
|
344
|
-
Some(AgentId::new("leader")),
|
|
345
|
-
Some(TeamKey::new("teamA")),
|
|
346
|
-
);
|
|
347
|
-
let ok = tools.update_state("checkpoint note").expect("update_state ok");
|
|
348
|
-
let v = serde_json::to_value(&ok).unwrap();
|
|
349
|
-
assert_eq!(v.get("ok"), Some(&json!(true)));
|
|
350
|
-
assert!(v.get("state_file").and_then(Value::as_str).is_some(),
|
|
351
|
-
"update_state returns the rewritten team_state.md path");
|
|
352
|
-
}
|
|
353
|
-
|
|
354
293
|
// ════════════════════════════════════════════════════════════════════════
|
|
355
294
|
// RpcId / RpcResponse byte-stability — null id echoed, error frame shape.
|
|
356
295
|
// ════════════════════════════════════════════════════════════════════════
|
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
#[test]
|
|
2
2
|
fn mcp_tool_wire_names_and_parse_roundtrip() {
|
|
3
3
|
let names = [
|
|
4
|
-
(McpTool::AssignTask, "assign_task"),
|
|
5
4
|
(McpTool::SendMessage, "send_message"),
|
|
6
5
|
(McpTool::ReportResult, "report_result"),
|
|
7
|
-
(McpTool::UpdateState, "update_state"),
|
|
8
6
|
(McpTool::GetTeamStatus, "get_team_status"),
|
|
9
|
-
(McpTool::StopAgent, "stop_agent"),
|
|
10
|
-
(McpTool::ResetAgent, "reset_agent"),
|
|
11
|
-
(McpTool::AddAgent, "add_agent"),
|
|
12
|
-
(McpTool::CloneAgent, "clone_agent"),
|
|
13
|
-
(McpTool::ForkAgent, "fork_agent"),
|
|
14
|
-
(McpTool::RequestHuman, "request_human"),
|
|
15
|
-
(McpTool::StuckList, "stuck_list"),
|
|
16
|
-
(McpTool::StuckCancel, "stuck_cancel"),
|
|
17
7
|
];
|
|
18
8
|
for (tool, name) in names {
|
|
19
9
|
assert_eq!(tool.wire_name(), name);
|
|
@@ -45,27 +35,13 @@ fn rpc_method_classify() {
|
|
|
45
35
|
// tools_contract — TOOLS wire list, exact names+order
|
|
46
36
|
// ════════════════════════════════════════════════════════════════════════
|
|
47
37
|
#[test]
|
|
48
|
-
fn
|
|
38
|
+
fn tools_contract_has_three_tools_in_order() {
|
|
49
39
|
let tools = tools_contract();
|
|
50
|
-
assert_eq!(tools.len(),
|
|
40
|
+
assert_eq!(tools.len(), 3);
|
|
51
41
|
let got: Vec<&str> = tools.iter().map(|t| t["name"].as_str().unwrap()).collect();
|
|
52
42
|
assert_eq!(
|
|
53
43
|
got,
|
|
54
|
-
vec![
|
|
55
|
-
"assign_task",
|
|
56
|
-
"send_message",
|
|
57
|
-
"report_result",
|
|
58
|
-
"update_state",
|
|
59
|
-
"get_team_status",
|
|
60
|
-
"stop_agent",
|
|
61
|
-
"reset_agent",
|
|
62
|
-
"add_agent",
|
|
63
|
-
"clone_agent",
|
|
64
|
-
"fork_agent",
|
|
65
|
-
"request_human",
|
|
66
|
-
"stuck_list",
|
|
67
|
-
"stuck_cancel",
|
|
68
|
-
]
|
|
44
|
+
vec!["send_message", "report_result", "get_team_status"]
|
|
69
45
|
);
|
|
70
46
|
// each carries description + inputSchema
|
|
71
47
|
for t in &tools {
|
|
@@ -89,32 +65,11 @@ fn tools_contract_has_thirteen_tools_in_order() {
|
|
|
89
65
|
"{internal} is framework-owned, not caller-supplied"
|
|
90
66
|
);
|
|
91
67
|
}
|
|
92
|
-
let
|
|
68
|
+
let status = tools
|
|
93
69
|
.iter()
|
|
94
|
-
.find(|tool| tool["name"] == json!("
|
|
70
|
+
.find(|tool| tool["name"] == json!("get_team_status"))
|
|
95
71
|
.unwrap();
|
|
96
|
-
assert_eq!(
|
|
97
|
-
clone["description"],
|
|
98
|
-
json!("Clone a worker role into a fresh provider session.")
|
|
99
|
-
);
|
|
100
|
-
assert_eq!(clone["inputSchema"]["additionalProperties"], json!(false));
|
|
101
|
-
assert_eq!(
|
|
102
|
-
clone["inputSchema"]["required"],
|
|
103
|
-
json!(["source_agent_id", "as_agent_id"])
|
|
104
|
-
);
|
|
105
|
-
assert_eq!(
|
|
106
|
-
clone["inputSchema"]["properties"]
|
|
107
|
-
.as_object()
|
|
108
|
-
.unwrap()
|
|
109
|
-
.keys()
|
|
110
|
-
.cloned()
|
|
111
|
-
.collect::<BTreeSet<_>>(),
|
|
112
|
-
BTreeSet::from([
|
|
113
|
-
"as_agent_id".to_string(),
|
|
114
|
-
"label".to_string(),
|
|
115
|
-
"source_agent_id".to_string(),
|
|
116
|
-
])
|
|
117
|
-
);
|
|
72
|
+
assert_eq!(status["description"], json!("Return machine-readable team status."));
|
|
118
73
|
}
|
|
119
74
|
|
|
120
75
|
#[test]
|
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
//!
|
|
2
|
-
//! purpose: MCP no-compaction contract test with fixture-owned workspace and path provenance
|
|
3
|
-
//! contract:
|
|
4
|
-
//! provides:
|
|
5
|
-
//! - name: mcp_state_fixture
|
|
6
|
-
//! what: supplies explicit process-owned workspace and state-file paths without mutating process-global environment
|
|
7
|
-
//! - name: mcp_state_path_provenance
|
|
8
|
-
//! what: records raw/canonical workspace, resolved state path, and filesystem ownership facts
|
|
9
|
-
//! depends:
|
|
10
|
-
//! - crate::mcp_server::lifecycle_tools::state_status
|
|
11
|
-
//! - crate::state::selector
|
|
12
|
-
//! boundary:
|
|
13
|
-
//! - the owned no-compaction test writes only within its fixture root
|
|
14
|
-
//! - this suite does not alter persistence semantics
|
|
15
|
-
//! maturity: wired
|
|
16
|
-
//! ---
|
|
17
|
-
//! step 14a · mcp_server::tests — WAVE-2 RED contracts (Python v0.2.11 golden).
|
|
1
|
+
//! MCP server unit-test fixtures and focused stdio/wire contract tests.
|
|
18
2
|
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
|
|
19
3
|
|
|
20
4
|
use super::*;
|
|
21
5
|
use serde_json::json;
|
|
22
|
-
use sha2::{Digest, Sha256};
|
|
23
6
|
use std::path::{Path, PathBuf};
|
|
24
7
|
|
|
25
8
|
// ── helpers ──────────────────────────────────────────────────────────────
|
|
@@ -35,11 +18,9 @@ fn keys(v: &Value) -> Vec<String> {
|
|
|
35
18
|
v.as_object().unwrap().keys().cloned().collect()
|
|
36
19
|
}
|
|
37
20
|
|
|
38
|
-
/// A UNIQUE throwaway workspace dir per test
|
|
39
|
-
///
|
|
40
|
-
|
|
41
|
-
/// Pure-function / dispatch-shape tests that never touch fs/db keep a dummy fixed path.
|
|
42
|
-
fn unique_ws(tag: &str) -> std::path::PathBuf {
|
|
21
|
+
/// A UNIQUE throwaway workspace dir per test. Filesystem and database tests
|
|
22
|
+
/// must not share `/tmp/ws` under parallel cargo.
|
|
23
|
+
fn unique_ws(tag: &str) -> PathBuf {
|
|
43
24
|
use std::io::ErrorKind;
|
|
44
25
|
use std::sync::atomic::{AtomicU64, Ordering};
|
|
45
26
|
static N: AtomicU64 = AtomicU64::new(0);
|
|
@@ -54,183 +35,6 @@ fn unique_ws(tag: &str) -> std::path::PathBuf {
|
|
|
54
35
|
}
|
|
55
36
|
}
|
|
56
37
|
|
|
57
|
-
static MCP_FIXTURE_SEQ: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
|
|
58
|
-
|
|
59
|
-
/// One process-owned root for update_state tests. All paths are passed explicitly
|
|
60
|
-
/// to the code under test; the fixture never changes process-global environment.
|
|
61
|
-
struct McpStateFixture {
|
|
62
|
-
root: PathBuf,
|
|
63
|
-
workspace: PathBuf,
|
|
64
|
-
receipt: PathBuf,
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
impl McpStateFixture {
|
|
68
|
-
fn new(_tag: &str) -> Self {
|
|
69
|
-
let seq = MCP_FIXTURE_SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
|
70
|
-
let base = if cfg!(target_os = "macos") {
|
|
71
|
-
PathBuf::from("/private/tmp")
|
|
72
|
-
} else {
|
|
73
|
-
PathBuf::from("/tmp")
|
|
74
|
-
};
|
|
75
|
-
let raw_root = base.join(format!("ta-mcp-{}-{seq}", std::process::id()));
|
|
76
|
-
std::fs::create_dir(&raw_root).unwrap();
|
|
77
|
-
let root = std::fs::canonicalize(raw_root).unwrap();
|
|
78
|
-
let workspace = root.join("workspace");
|
|
79
|
-
let receipt = root
|
|
80
|
-
.parent()
|
|
81
|
-
.unwrap()
|
|
82
|
-
.join(format!("ta-mcp-receipt-{}-{seq}.json", std::process::id()));
|
|
83
|
-
std::fs::create_dir(&workspace).unwrap();
|
|
84
|
-
|
|
85
|
-
let fixture = Self {
|
|
86
|
-
root,
|
|
87
|
-
workspace,
|
|
88
|
-
receipt,
|
|
89
|
-
};
|
|
90
|
-
fixture.seed_spec("team_state.md");
|
|
91
|
-
crate::state::repository::StateRepository::new(&fixture.workspace)
|
|
92
|
-
.save(
|
|
93
|
-
crate::state::repository::StateWriteIntent::FakeE2eSeed,
|
|
94
|
-
&json!({
|
|
95
|
-
"session_name": "mcp-fixture",
|
|
96
|
-
"active_team_key": "current",
|
|
97
|
-
"agents": {},
|
|
98
|
-
"tasks": []
|
|
99
|
-
}),
|
|
100
|
-
)
|
|
101
|
-
.unwrap();
|
|
102
|
-
fixture
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
fn seed_spec(&self, state_file: &str) {
|
|
106
|
-
std::fs::write(
|
|
107
|
-
self.workspace.join("team.spec.yaml"),
|
|
108
|
-
format!(
|
|
109
|
-
"team:\n name: mcp-fixture\n objective: path contract\nagents: []\ntasks: []\ncontext:\n state_file: {state_file}\n"
|
|
110
|
-
),
|
|
111
|
-
)
|
|
112
|
-
.unwrap();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
fn state_file(&self, relative: &str) -> PathBuf {
|
|
116
|
-
self.workspace.join(relative)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
fn record_provenance(&self, raw_workspace: &Path, state_file: &Path) -> PathBuf {
|
|
120
|
-
let canonical_workspace =
|
|
121
|
-
crate::model::paths::canonical_run_workspace(raw_workspace).unwrap();
|
|
122
|
-
assert!(self.under_root(raw_workspace));
|
|
123
|
-
assert!(self.under_root(&canonical_workspace));
|
|
124
|
-
assert!(self.under_root(state_file));
|
|
125
|
-
let team_dir = self.workspace.join(".team");
|
|
126
|
-
let runtime_dir = team_dir.join("runtime");
|
|
127
|
-
let runtime_state = crate::state::persist::runtime_state_path(&self.workspace);
|
|
128
|
-
let paths = [
|
|
129
|
-
("root", self.root.as_path()),
|
|
130
|
-
("raw_workspace", raw_workspace),
|
|
131
|
-
("canonical_workspace", canonical_workspace.as_path()),
|
|
132
|
-
("team_dir", team_dir.as_path()),
|
|
133
|
-
("runtime_dir", runtime_dir.as_path()),
|
|
134
|
-
("state_parent", state_file.parent().unwrap()),
|
|
135
|
-
("runtime_state", runtime_state.as_path()),
|
|
136
|
-
];
|
|
137
|
-
let mut facts = paths
|
|
138
|
-
.into_iter()
|
|
139
|
-
.map(|(name, path)| {
|
|
140
|
-
let metadata = std::fs::symlink_metadata(path).unwrap();
|
|
141
|
-
json!({
|
|
142
|
-
"name": name,
|
|
143
|
-
"path": path.display().to_string(),
|
|
144
|
-
"uid": metadata_uid(&metadata),
|
|
145
|
-
"mode": metadata_mode(&metadata),
|
|
146
|
-
"device": metadata_device(&metadata)
|
|
147
|
-
})
|
|
148
|
-
})
|
|
149
|
-
.collect::<Vec<_>>();
|
|
150
|
-
if let Ok(metadata) = std::fs::symlink_metadata(state_file) {
|
|
151
|
-
facts.push(json!({
|
|
152
|
-
"name": "state_file",
|
|
153
|
-
"path": state_file.display().to_string(),
|
|
154
|
-
"uid": metadata_uid(&metadata),
|
|
155
|
-
"mode": metadata_mode(&metadata),
|
|
156
|
-
"device": metadata_device(&metadata)
|
|
157
|
-
}));
|
|
158
|
-
}
|
|
159
|
-
let payload = json!({
|
|
160
|
-
"raw_workspace": raw_workspace.display().to_string(),
|
|
161
|
-
"canonical_workspace": canonical_workspace.display().to_string(),
|
|
162
|
-
"resolved_state_file": state_file.display().to_string(),
|
|
163
|
-
"runtime_state_path": runtime_state.display().to_string(),
|
|
164
|
-
"facts": facts
|
|
165
|
-
});
|
|
166
|
-
let payload_bytes = serde_json::to_vec(&payload).unwrap();
|
|
167
|
-
let payload_sha256 = format!("{:x}", Sha256::digest(&payload_bytes));
|
|
168
|
-
let receipt = json!({
|
|
169
|
-
"schema": "mcp-state-provenance-v1",
|
|
170
|
-
"payload": payload,
|
|
171
|
-
"payload_sha256": payload_sha256
|
|
172
|
-
});
|
|
173
|
-
let receipt_bytes = serde_json::to_vec_pretty(&receipt).unwrap();
|
|
174
|
-
use std::io::Write;
|
|
175
|
-
let mut file = std::fs::OpenOptions::new()
|
|
176
|
-
.write(true)
|
|
177
|
-
.create_new(true)
|
|
178
|
-
.open(&self.receipt)
|
|
179
|
-
.unwrap();
|
|
180
|
-
file.write_all(&receipt_bytes).unwrap();
|
|
181
|
-
file.sync_all().unwrap();
|
|
182
|
-
self.receipt.clone()
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
fn under_root(&self, path: &Path) -> bool {
|
|
186
|
-
let candidate = if path.exists() {
|
|
187
|
-
std::fs::canonicalize(path).unwrap()
|
|
188
|
-
} else {
|
|
189
|
-
path.to_path_buf()
|
|
190
|
-
};
|
|
191
|
-
candidate.starts_with(&self.root)
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
impl Drop for McpStateFixture {
|
|
196
|
-
fn drop(&mut self) {
|
|
197
|
-
let _ = std::fs::remove_dir_all(&self.root);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
#[cfg(unix)]
|
|
202
|
-
fn metadata_uid(metadata: &std::fs::Metadata) -> u32 {
|
|
203
|
-
use std::os::unix::fs::MetadataExt;
|
|
204
|
-
metadata.uid()
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
#[cfg(not(unix))]
|
|
208
|
-
fn metadata_uid(_: &std::fs::Metadata) -> u32 {
|
|
209
|
-
0
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
#[cfg(unix)]
|
|
213
|
-
fn metadata_mode(metadata: &std::fs::Metadata) -> u32 {
|
|
214
|
-
use std::os::unix::fs::MetadataExt;
|
|
215
|
-
metadata.mode()
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
#[cfg(not(unix))]
|
|
219
|
-
fn metadata_mode(_: &std::fs::Metadata) -> u32 {
|
|
220
|
-
0
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
#[cfg(unix)]
|
|
224
|
-
fn metadata_device(metadata: &std::fs::Metadata) -> u64 {
|
|
225
|
-
use std::os::unix::fs::MetadataExt;
|
|
226
|
-
metadata.dev()
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
#[cfg(not(unix))]
|
|
230
|
-
fn metadata_device(_: &std::fs::Metadata) -> u64 {
|
|
231
|
-
0
|
|
232
|
-
}
|
|
233
|
-
|
|
234
38
|
include!("tests/normalize.rs");
|
|
235
39
|
include!("tests/wire.rs");
|
|
236
40
|
include!("tests/send.rs");
|