Skip to content
Merged
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
70 changes: 65 additions & 5 deletions crates/pkg/src/changelog/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,19 +836,74 @@ impl ChangelogGenerator {
Ok(changelog)
}

/// Checks if a Git reference (tag, branch, or commit) exists in the repository.
///
/// This method attempts to resolve a Git reference using `revparse_single`.
/// If the reference can be resolved, it exists; otherwise, it does not.
///
/// # Arguments
///
/// * `git_ref` - The Git reference to check (tag name, branch name, or commit SHA)
///
/// # Returns
///
/// Returns `true` if the reference exists and can be resolved, `false` otherwise.
///
/// # Examples
///
/// ```rust,ignore
/// # use sublime_pkg_tools::changelog::ChangelogGenerator;
/// # use sublime_pkg_tools::config::PackageToolsConfig;
/// # use sublime_git_tools::Repo;
/// # use sublime_standard_tools::filesystem::FileSystemManager;
/// # use std::path::PathBuf;
/// #
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// # let workspace_root = PathBuf::from(".");
/// # let git_repo = Repo::open(".")?;
/// # let fs = FileSystemManager::new();
/// # let config = PackageToolsConfig::default();
/// #
/// let generator = ChangelogGenerator::new(
/// workspace_root,
/// git_repo,
/// fs,
/// config.changelog,
/// ).await?;
///
/// // Check if a tag exists
/// if generator.reference_exists("v1.0.0") {
/// println!("Tag v1.0.0 exists");
/// }
///
/// // HEAD always exists
/// assert!(generator.reference_exists("HEAD"));
/// # Ok(())
/// # }
/// ```
#[must_use]
fn reference_exists(&self, git_ref: &str) -> bool {
// Use the git_repo's internal repo to check if reference exists
// This is a simple check - if revparse_single succeeds, the reference exists
self.git_repo.get_diverged_commit(git_ref).is_ok()
}

/// Builds Git references for changelog generation.
///
/// Creates the from and to references based on the configured tag format.
/// When the target version tag does not exist yet (common during changelog
/// generation before tags are created), this method automatically falls back
/// to using `HEAD` as the `to_ref`.
///
/// # Arguments
///
/// * `package_name` - Optional package name
/// * `previous_version` - Optional previous version
/// * `current_version` - Current version
/// * `package_name` - Optional package name for scoped packages
/// * `previous_version` - Optional previous version string
/// * `current_version` - Current version string
///
/// # Returns
///
/// A tuple of (from_ref, to_ref) strings.
/// A tuple of (from_ref, to_ref) strings representing Git references.
///
/// # Errors
///
Expand All @@ -866,12 +921,17 @@ impl ChangelogGenerator {
};

// Build to_ref (current version tag)
let to_ref = if let Some(pkg_name) = package_name {
let to_ref_tag = if let Some(pkg_name) = package_name {
format.replace("{name}", pkg_name).replace("{version}", current_version)
} else {
format.replace("{version}", current_version)
};

// Check if the to_ref tag exists; if not, use HEAD
// This handles the case where changelog is generated before tags are created
let to_ref =
if self.reference_exists(&to_ref_tag) { to_ref_tag } else { "HEAD".to_string() };

// Build from_ref (previous version tag or HEAD)
let from_ref = if let Some(prev_version) = previous_version {
if let Some(pkg_name) = package_name {
Expand Down