Typemap / exclusive-lock (+l) manager for Unreal binaries
- Tools -> Exclusive Locks (typemap): view/edit server typemap, one-click add recommended binary+l rules for UE asset types (.uasset/.umap/.fbx/textures/etc) - Per-file 'Set exclusive-lock type (+l)' in the Changes context menu - Backend p4 typemap -o/-i and reopen -t Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1314,6 +1314,87 @@ async fn p4_unlock(state: State<'_, AppState>, files: Vec<String>) -> Result<Str
|
||||
run_text(&conn, &args)
|
||||
}
|
||||
|
||||
/// Read the server typemap as a list of "TYPE PATTERN" entries.
|
||||
/// (Empty list if the typemap is unset. Requires admin to *change*, not to read.)
|
||||
#[tauri::command]
|
||||
async fn p4_typemap_get(state: State<'_, AppState>) -> Result<Vec<String>, String> {
|
||||
let conn = current(&state)?;
|
||||
let spec = run_text(&conn, &["typemap", "-o"])?;
|
||||
let mut entries = Vec::new();
|
||||
let mut in_map = false;
|
||||
for line in spec.lines() {
|
||||
if line.starts_with("TypeMap:") {
|
||||
in_map = true;
|
||||
continue;
|
||||
}
|
||||
if in_map {
|
||||
if line.starts_with('\t') || line.starts_with(' ') {
|
||||
let e = line.trim();
|
||||
if !e.is_empty() && !e.starts_with('#') {
|
||||
entries.push(e.to_string());
|
||||
}
|
||||
} else if !line.trim().is_empty() {
|
||||
break; // reached the next spec field
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
/// Replace the server typemap with the given "TYPE PATTERN" entries.
|
||||
/// Requires admin rights on the server.
|
||||
#[tauri::command]
|
||||
async fn p4_typemap_set(state: State<'_, AppState>, entries: Vec<String>) -> Result<String, String> {
|
||||
let conn = current(&state)?;
|
||||
let mut spec = String::from("TypeMap:\n");
|
||||
for e in &entries {
|
||||
let e = e.trim();
|
||||
if !e.is_empty() {
|
||||
spec.push('\t');
|
||||
spec.push_str(e);
|
||||
spec.push('\n');
|
||||
}
|
||||
}
|
||||
let mut child = p4_cmd(&conn, false)
|
||||
.args(["typemap", "-i"])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to start p4: {e}"))?;
|
||||
if let Some(si) = child.stdin.as_mut() {
|
||||
si.write_all(spec.as_bytes()).map_err(|e| e.to_string())?;
|
||||
}
|
||||
let out = child.wait_with_output().map_err(|e| e.to_string())?;
|
||||
if !out.status.success() {
|
||||
let err = decode(&out.stderr);
|
||||
let msg = if err.trim().is_empty() { decode(&out.stdout) } else { err };
|
||||
let low = msg.to_lowercase();
|
||||
return Err(if low.contains("permission") || low.contains("protect") || low.contains("admin") || low.contains("not allowed") {
|
||||
"You need admin rights on the server to change the typemap.".to_string()
|
||||
} else {
|
||||
msg.trim().to_string()
|
||||
});
|
||||
}
|
||||
Ok(decode(&out.stdout).trim().to_string())
|
||||
}
|
||||
|
||||
/// Change the Perforce file type of opened files (e.g. add "+l" exclusive lock).
|
||||
/// `filetype` is passed to `p4 reopen -t`, so "+l" adds the modifier and
|
||||
/// "binary+l" sets the full type.
|
||||
#[tauri::command]
|
||||
async fn p4_reopen_type(state: State<'_, AppState>, files: Vec<String>, filetype: String) -> Result<String, String> {
|
||||
let conn = current(&state)?;
|
||||
if files.is_empty() {
|
||||
return Ok(String::new());
|
||||
}
|
||||
let mut args: Vec<&str> = vec!["reopen", "-t", &filetype];
|
||||
for f in &files {
|
||||
args.push(f.as_str());
|
||||
}
|
||||
run_text(&conn, &args)
|
||||
}
|
||||
|
||||
/// Extract the largest embedded PNG from a byte blob — this is how an uncooked
|
||||
/// Unreal `.uasset` stores its Content-Browser thumbnail (PNG-compressed in the
|
||||
/// package thumbnail table). We scan for the PNG signature → IEND and keep the
|
||||
@ -1924,6 +2005,9 @@ pub fn run() {
|
||||
p4_opened_all,
|
||||
p4_lock,
|
||||
p4_unlock,
|
||||
p4_typemap_get,
|
||||
p4_typemap_set,
|
||||
p4_reopen_type,
|
||||
uasset_thumbnail,
|
||||
uasset_export_3d,
|
||||
p4_shelve,
|
||||
|
||||
Reference in New Issue
Block a user