Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 0 additions & 109 deletions xsync/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@
# It is not intended for manual editing.
version = 4

[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]

[[package]]
name = "anstream"
version = "0.6.18"
Expand Down Expand Up @@ -94,14 +85,6 @@ dependencies = [
"toml",
]

[[package]]
name = "ci_logger"
version = "0.0.0"
dependencies = [
"env_logger",
"log",
]

[[package]]
name = "clap"
version = "4.5.32"
Expand Down Expand Up @@ -165,29 +148,6 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"

[[package]]
name = "env_filter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
]

[[package]]
name = "env_logger"
version = "0.11.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"jiff",
"log",
]

[[package]]
name = "equivalent"
version = "1.0.2"
Expand Down Expand Up @@ -379,30 +339,6 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"

[[package]]
name = "jiff"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e"
dependencies = [
"jiff-static",
"log",
"portable-atomic",
"portable-atomic-util",
"serde",
]

[[package]]
name = "jiff-static"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

[[package]]
name = "litemap"
version = "0.7.5"
Expand Down Expand Up @@ -433,21 +369,6 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"

[[package]]
name = "portable-atomic"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"

[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]

[[package]]
name = "proc-macro2"
version = "1.0.94"
Expand All @@ -466,35 +387,6 @@ dependencies = [
"proc-macro2",
]

[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]

[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]

[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"

[[package]]
name = "semver"
version = "1.0.26"
Expand Down Expand Up @@ -753,7 +645,6 @@ dependencies = [
"anyhow",
"cargo-lock",
"cargo_toml",
"ci_logger",
"clap",
"dunce",
"fs-err",
Expand Down
9 changes: 0 additions & 9 deletions xsync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,6 @@ semver = "1.0"
serde = "1.0.185"
toml_edit = "0.22"

# HACK: this is exactly the kind of dependency we _don't_ want to have in this
# tooling, since the moment ci_logger moves on the filesystem / has an
# incompatible API update, the tooling in this repo will stop working!
#
# ...that said, given the scope of this particular dep, its likelihood to stay
# in the same place for the forseeable future, and the current time crunch...
# we're going to risk it and take this dep anyways.
ci_logger = { path = "../support/ci_logger" }

# TODO: would be nice to enforce that these lints are also kept in-sync with
# outer workspace
[workspace.lints.rust]
Expand Down
4 changes: 2 additions & 2 deletions xsync/xsync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ cargo-lock.workspace = true
clap = { workspace = true, features = ["derive", "env"] }
dunce.workspace = true
fs-err.workspace = true
log.workspace = true
log = { workspace = true, features = ["std"] }
pathdiff.workspace = true
semver.workspace = true
serde = { workspace = true, features = ["std"] }
toml_edit = { workspace = true, features = ["serde"] }

ci_logger.workspace = true


[lints]
workspace = true
92 changes: 92 additions & 0 deletions xsync/xsync/src/log_init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! A [`log::Log`] implementation that translates log-levels to ADO logging
//! commands when running in CI, and uses ANSI colors otherwise.
//!
//! Inlined from `ci_logger` to avoid a cross-workspace path dependency.

use log::Level;
use log::LevelFilter;
use log::Metadata;
use log::Record;

struct AdoLogger {
max_level: LevelFilter,
in_ci: bool,
}

impl AdoLogger {
fn new(log_level: Option<&str>) -> AdoLogger {
let max_level = match log_level.map(|s| s.to_lowercase()).as_deref() {
Some("trace") => LevelFilter::Trace,
Some("debug") => LevelFilter::Debug,
Some("info") => LevelFilter::Info,
Some("warn" | "warning") => LevelFilter::Warn,
Some("error") => LevelFilter::Error,
Some("off") => LevelFilter::Off,
_ => LevelFilter::Info,
Comment on lines +20 to +28
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XSYNC_LOG used to accept full env_logger filter syntax via ci_logger (e.g. module=debug,other=warn). This reimplementation only recognizes a few exact strings and silently falls back to Info for anything else, which can make existing configs appear to “stop working”. Consider either (a) supporting a minimal subset of the previous filter syntax (at least target=level / comma-separated), or (b) treating unrecognized values as an error (or at least printing a one-time warning to stderr before installing the logger) so misconfiguration is visible.

Suggested change
fn new(log_level: Option<&str>) -> AdoLogger {
let max_level = match log_level.map(|s| s.to_lowercase()).as_deref() {
Some("trace") => LevelFilter::Trace,
Some("debug") => LevelFilter::Debug,
Some("info") => LevelFilter::Info,
Some("warn" | "warning") => LevelFilter::Warn,
Some("error") => LevelFilter::Error,
Some("off") => LevelFilter::Off,
_ => LevelFilter::Info,
fn parse_level_filter(log_level: &str) -> Option<LevelFilter> {
match log_level.trim().to_ascii_lowercase().as_str() {
"trace" => Some(LevelFilter::Trace),
"debug" => Some(LevelFilter::Debug),
"info" => Some(LevelFilter::Info),
"warn" | "warning" => Some(LevelFilter::Warn),
"error" => Some(LevelFilter::Error),
"off" => Some(LevelFilter::Off),
_ => None,
}
}
fn new(log_level: Option<&str>) -> AdoLogger {
let max_level = match log_level {
Some(value) => match Self::parse_level_filter(value) {
Some(level) => level,
None => {
eprintln!(
"warning: unrecognized log level {:?}; falling back to 'info'. Supported values: trace, debug, info, warn, warning, error, off.",
value
);
LevelFilter::Info
}
},
None => LevelFilter::Info,

Copilot uses AI. Check for mistakes.
};

AdoLogger {
in_ci: std::env::var("TF_BUILD").is_ok(),
max_level,
}
}
}

impl log::Log for AdoLogger {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
metadata.level() <= self.max_level
}

fn log(&self, record: &Record<'_>) {
if record.level() <= self.max_level {
let (prefix, postfix) = if self.in_ci {
let prefix = match record.level() {
Level::Error => "##vso[task.logissue type=error]",
Level::Warn => "##vso[task.logissue type=warning]",
Level::Info => "",
Level::Debug => "##[debug]",
Level::Trace => "##[debug](trace)",
};
(prefix, "")
} else {
let prefix = match record.level() {
Level::Error => "\x1B[0;31m", // red
Level::Warn => "\x1B[0;33m", // yellow
Level::Info => "",
Level::Debug => "\x1B[0;36m", // cyan
Level::Trace => "\x1B[0;35m", // purple
};
(prefix, "\x1B[0m")
};

if record.level() <= Level::Info {
eprintln!("{}{}{}", prefix, record.args(), postfix)
} else {
eprintln!(
"{}[{}:{}] {}{}",
prefix,
record.module_path().unwrap_or("?"),
record
.line()
.map(|s| s.to_string())
.unwrap_or_else(|| "?".into()),
record.args(),
postfix
)
}
}
}

fn flush(&self) {}
}

/// Initialize the ADO logger
pub fn init(log_env_var: &str) -> Result<(), log::SetLoggerError> {
log::set_boxed_logger(Box::new(AdoLogger::new(
std::env::var(log_env_var).ok().as_deref(),
)))
.map(|()| log::set_max_level(LevelFilter::Trace))
}
3 changes: 2 additions & 1 deletion xsync/xsync/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use clap::Parser;
use clap::Subcommand;
use std::path::PathBuf;

mod log_init;
mod tasks;

/// Default location to maintain a `xsync-path` file
Expand Down Expand Up @@ -62,7 +63,7 @@ enum Commands {
}

fn main() {
ci_logger::init("XSYNC_LOG").unwrap();
log_init::init("XSYNC_LOG").unwrap();

if let Err(e) = try_main() {
log::error!("Error: {:#}", e);
Expand Down
Loading