Repository: orhun/git-cliff (language: python)

Issue:
Make repository name available in context
### Is there an existing issue or pull request for this?

- [X] I have searched the existing issues and pull requests

### Feature description

I am creating a consolidated changelog for multiple repositories building a monolith using the `--repository` flag with three repos. The changelog gets generated but theres no reference which changelog refers to which repo, just the repos most current tags.
In the current context there's just details about commits but not about the repo name or url.

### Desired solution

It would be nice to have the repo name (and url?) available in the context to have something like this:

`config:` [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} -- {{ repo.name }}

which would look like this: 

## [1.2.3] - 2024-06-07 - orhun/git-cliff

changes ...

## [4.5.6] - 2024-06-07 - another/repo

changes...

### Alternatives considered

The closes thing I currently see to achieve this are commit parsers which allow me to run commands on the OS. But I am not sure how to use that in the body heading to call git and get the repo name. I tried putting a placeholder in the body
`## [unreleased] - REPO_URL` and then tried a postprocessor:

postprocessors = [
  { pattern = 'REPO_URL', replace_command = "basename -s .git `git config --get remote.origin.url`" },
]

this leads to the entire changelog dissappering and setting the reponame where the CI runs three times and not the individual ones :( 

### Additional context

_No response_


Discussion / hints:
Thanks for opening your first issue at **git-cliff**! Be sure to follow the issue template! ⛰️

Hello!

You can do something like this:

```sh
git cliff --github-repo orhun/git-cliff
```

Then in the template:

```
{{ remote.github.owner }}/{{ remote.github.repo }}
```

See the following links for more information:

- https://git-cliff.org/docs/configuration/remote
- https://git-cliff.org/docs/integration/github
that sounds good but i am using a selfhosted Gitlab. Do i have to compile cliff to be able to use it? and does it work for multiple repos or just one?
Similarly, you can do the same for GitLab:

```sh
GITLAB_API_URL="<your self hosted url>" git cliff --gitlab-repo orhun/git-cliff
```

Then in the template:

```
{{ remote.gitlab.owner }}/{{ remote.gitlab.repo }}
```

See the following links for more information:

- https://git-cliff.org/docs/configuration/remote
- https://git-cliff.org/docs/integration/gitlab


Thanks a lot for the idea and docs links but this is still not working.

When I use three repos, the one with changes and the CI and two other ones with their changes.
If I run git cliff with API URL, token and --gitlab-repo path1/repo1 --repository= ./ path2/repo2 path3/repo3

In the result changelog all repos have the reponame repo1 when using `{{ remote.gitlab.repo }}`

Oh, it's expected that it might not work with multiple repos. I didn't try it out like that before and it's fetching the commits for only one repo...
ohh, ok, thanks a lot for checking! But could you make it possible to read the repos in the base implementation as part of the --repository flag and independent of the gitlab/github/... integrations?
In the individual repo folders you got all the info present about the repos and its not so useful to aggregate changes and not not knowing where they come from :(

this is an awesome project and this addition would make it a very valuable tool
> ohh, ok, thanks a lot for checking! But could you make it possible to read the repos in the base implementation as part of the --repository flag and independent of the gitlab/github/... integrations?

Do you mean making e.g. the directory name available in context? 
Yes the directory name would work
Okay, I just checked and I'm not sure where in context we can add the repository path.

The context is currently an array of releases, updating that structure will be a breaking change.
Thank you very much for your effort, I have no experience in Rust yet and can't make a code suggestion myself :(
Can't you append the repo name at the same position where you keep the repos tag version number? Or is that not a kind of list/array?
You can take a look at https://git-cliff.org/docs/templating/context for getting an idea.

To oversimplify it:

```json
[
  {
    "version": "v0.1.0-rc.21"
  },
  {
    "version": "v0.1.0-rc.20"
  }
]
```

We can add the repo path to each item here, but it would be really redundant :/
If theres just a changelog created for the current repo its not really needed, I agree. But when using the --repository flag and multiple repos it should be a good addition in my opinion.

I also tried it with a postporcessor and some git commands and a replace of a placeholder, but that made the whole changelog disappear and just header and footer were left. I am at a different computer this week and can't access the snippet currently

Fix patch:
diff --git a/git-cliff-core/src/changelog.rs b/git-cliff-core/src/changelog.rs
index 5680d49f76..c6a84d9986 100644
--- a/git-cliff-core/src/changelog.rs
+++ b/git-cliff-core/src/changelog.rs
@@ -613,7 +613,7 @@ mod test {
 				header:         Some(String::from("# Changelog")),
 				body:           Some(String::from(
 					r#"{% if version %}
-				## Release [{{ version }}] - {{ timestamp | date(format="%Y-%m-%d") }}
+				## Release [{{ version }}] - {{ timestamp | date(format="%Y-%m-%d") }} - ({{ repository }})
 				{% if commit_id %}({{ commit_id }}){% endif %}{% else %}
 				## Unreleased{% endif %}
 				{% for group, commits in commits | group_by(attribute="group") %}
@@ -881,6 +881,7 @@ mod test {
 			commit_id: Some(String::from("0bc123")),
 			timestamp: 50000000,
 			previous: None,
+			repository: Some(String::from("/root/repo")),
 			#[cfg(feature = "github")]
 			github: crate::remote::RemoteReleaseMetadata {
 				contributors: vec![],
@@ -941,6 +942,7 @@ mod test {
 				commit_id: None,
 				timestamp: 1000,
 				previous: Some(Box::new(test_release)),
+				repository: Some(String::from("/root/repo")),
 				#[cfg(feature = "github")]
 				github: crate::remote::RemoteReleaseMetadata {
 					contributors: vec![],
@@ -974,7 +976,7 @@ mod test {
 			String::from(
 				r#"# Changelog
 
-			## Release [v1.1.0] - 1970-01-01
+			## Release [v1.1.0] - 1970-01-01 - (/root/repo)
 
 
 			### Bug Fixes
@@ -992,7 +994,7 @@ mod test {
 			#### ui
 			- do exciting stuff
 
-			## Release [v1.0.0] - 1971-08-02
+			## Release [v1.0.0] - 1971-08-02 - (/root/repo)
 			(0bc123)
 
 			### Bug Fixes
@@ -1117,7 +1119,7 @@ chore(deps): fix broken deps
 			#### app
 			- merge #5
 
-			## Release [v1.0.0] - 1971-08-02
+			## Release [v1.0.0] - 1971-08-02 - (/root/repo)
 			(0bc123)
 
 			### Bug Fixes
diff --git a/git-cliff-core/src/release.rs b/git-cliff-core/src/release.rs
index 05720d2572..9ee23835fa 100644
--- a/git-cliff-core/src/release.rs
+++ b/git-cliff-core/src/release.rs
@@ -20,30 +20,32 @@ use serde::{
 #[serde(rename_all = "camelCase")]
 pub struct Release<'a> {
 	/// Release version, git tag.
-	pub version:   Option<String>,
+	pub version:    Option<String>,
 	/// git tag's message.
-	pub message:   Option<String>,
+	pub message:    Option<String>,
 	/// Commits made for the release.
-	pub commits:   Vec<Commit<'a>>,
+	pub commits:    Vec<Commit<'a>>,
 	/// Commit ID of the tag.
 	#[serde(rename = "commit_id")]
-	pub commit_id: Option<String>,
+	pub commit_id:  Option<String>,
 	/// Timestamp of the release in seconds, from epoch.
-	pub timestamp: i64,
+	pub timestamp:  i64,
 	/// Previous release.
-	pub previous:  Option<Box<Release<'a>>>,
+	pub previous:   Option<Box<Release<'a>>>,
+	/// Repository path.
+	pub repository: Option<String>,
 	/// Contributors.
 	#[cfg(feature = "github")]
-	pub github:    RemoteReleaseMetadata,
+	pub github:     RemoteReleaseMetadata,
 	/// Contributors.
 	#[cfg(feature = "gitlab")]
-	pub gitlab:    RemoteReleaseMetadata,
+	pub gitlab:     RemoteReleaseMetadata,
 	/// Contributors.
 	#[cfg(feature = "gitea")]
-	pub gitea:     RemoteReleaseMetadata,
+	pub gitea:      RemoteReleaseMetadata,
 	/// Contributors.
 	#[cfg(feature = "bitbucket")]
-	pub bitbucket: RemoteReleaseMetadata,
+	pub bitbucket:  RemoteReleaseMetadata,
 }
 
 #[cfg(feature = "github")]
@@ -187,6 +189,7 @@ mod test {
 					version: Some(String::from(version)),
 					..Default::default()
 				})),
+				repository: Some(String::from("/root/repo")),
 				#[cfg(feature = "github")]
 				github: crate::remote::RemoteReleaseMetadata {
 					contributors: vec![],
@@ -395,6 +398,7 @@ mod test {
 				version: Some(String::from("1.0.0")),
 				..Default::default()
 			})),
+			repository: Some(String::from("/root/repo")),
 			github: RemoteReleaseMetadata {
 				contributors: vec![],
 			},
@@ -681,6 +685,7 @@ mod test {
 				version: Some(String::from("1.0.0")),
 				..Default::default()
 			})),
+			repository: Some(String::from("/root/repo")),
 			#[cfg(feature = "github")]
 			github: RemoteReleaseMetadata {
 				contributors: vec![],
@@ -1025,6 +1030,7 @@ mod test {
 				version: Some(String::from("1.0.0")),
 				..Default::default()
 			})),
+			repository: Some(String::from("/root/repo")),
 			#[cfg(feature = "github")]
 			github: RemoteReleaseMetadata {
 				contributors: vec![],
diff --git a/git-cliff-core/src/repo.rs b/git-cliff-core/src/repo.rs
index 50645c883d..25d9a23baf 100644
--- a/git-cliff-core/src/repo.rs
+++ b/git-cliff-core/src/repo.rs
@@ -32,7 +32,9 @@ static TAG_SIGNATURE_REGEX: Lazy<Regex> = lazy_regex!(
 ///
 /// [`Repository`]: GitRepository
 pub struct Repository {
-	inner: GitRepository,
+	inner:    GitRepository,
+	/// Repository path.
+	pub path: PathBuf,
 }
 
 impl Repository {
@@ -40,7 +42,8 @@ impl Repository {
 	pub fn init(path: PathBuf) -> Result<Self> {
 		if path.exists() {
 			Ok(Self {
-				inner: GitRepository::open(path)?,
+				inner: GitRepository::open(&path)?,
+				path,
 			})
 		} else {
 			Err(Error::IoError(io::Error::new(
diff --git a/git-cliff-core/src/template.rs b/git-cliff-core/src/template.rs
index 3fe0e8a3a9..6d2e611805 100644
--- a/git-cliff-core/src/template.rs
+++ b/git-cliff-core/src/template.rs
@@ -206,6 +206,7 @@ mod test {
 			commit_id: None,
 			timestamp: 0,
 			previous: None,
+			repository: Some(String::from("/root/repo")),
 			#[cfg(feature = "github")]
 			github: crate::remote::RemoteReleaseMetadata {
 				contributors: vec![],
diff --git a/git-cliff/src/lib.rs b/git-cliff/src/lib.rs
index 6fc8e8c458..a42da54993 100644
--- a/git-cliff/src/lib.rs
+++ b/git-cliff/src/lib.rs
@@ -245,6 +245,8 @@ fn process_repository<'a>(
 	for git_commit in commits.iter().rev() {
 		let commit = Commit::from(git_commit);
 		let commit_id = commit.id.to_string();
+		releases[release_index].repository =
+			Some(repository.path.to_string_lossy().to_string());
 		if args.sort == Sort::Newest {
 			releases[release_index].commits.insert(0, commit);
 		} else {
diff --git a/website/docs/templating/context.md b/website/docs/templating/context.md
index 9d61db8015..c979659e95 100644
--- a/website/docs/templating/context.md
+++ b/website/docs/templating/context.md
@@ -62,6 +62,7 @@ following context is generated to use for templating:
   ],
   "commit_id": "a440c6eb26404be4877b7e3ad592bfaa5d4eb210 (release commit)",
   "timestamp": 1625169301,
+  "repository": "/path/to/repository",
   "previous": {
     "version": "previous release"
   }
@@ -156,6 +157,7 @@ If [`conventional_commits`](/docs/configuration/git#conventional_commits) is set
   ],
   "commit_id": "a440c6eb26404be4877b7e3ad592bfaa5d4eb210 (release commit)",
   "timestamp": 1625169301,
+  "repository": "/path/to/repository",
   "previous": {
     "version": "previous release"
   }
diff --git a/website/docs/usage/multiple-repos.md b/website/docs/usage/multiple-repos.md
index d6fe294fd8..0e4a6bdd92 100644
--- a/website/docs/usage/multiple-repos.md
+++ b/website/docs/usage/multiple-repos.md
@@ -11,3 +11,11 @@ git cliff --repository path1 path2
 ```
 
 Note that the changelog will be generated using the merged history of the given repositories.
+
+:::tip
+
+You can use the `{{ repository }}` variable in the template to display which release belongs to which repository.
+
+See [context](/docs/templating/context) for more information.
+
+:::


Test patch:
diff --git a/git-cliff-core/tests/integration_test.rs b/git-cliff-core/tests/integration_test.rs
index 3e960fac69..47f2791d06 100644
--- a/git-cliff-core/tests/integration_test.rs
+++ b/git-cliff-core/tests/integration_test.rs
@@ -194,6 +194,7 @@ fn generate_changelog() -> Result<()> {
 			commit_id: None,
 			timestamp: 0,
 			previous:  None,
+			repository: Some(String::from("/root/repo")),
 			#[cfg(feature = "github")]
 			github: git_cliff_core::remote::RemoteReleaseMetadata {
 				contributors: vec![],
@@ -235,6 +236,7 @@ fn generate_changelog() -> Result<()> {
 			commit_id: None,
 			timestamp: 0,
 			previous:  None,
+			repository: Some(String::from("/root/repo")),
 			#[cfg(feature = "github")]
 			github: git_cliff_core::remote::RemoteReleaseMetadata {
 				contributors: vec![],