Skip to content

feat: overwrite git attrs with dirty status - #199

Merged
tisonkun merged 8 commits into
mainfrom
support-disk_file_modified_year
Jan 9, 2026
Merged

feat: overwrite git attrs with dirty status#199
tisonkun merged 8 commits into
mainfrom
support-disk_file_modified_year

Conversation

@tisonkun

@tisonkun tisonkun commented Jan 9, 2026

Copy link
Copy Markdown
Member

This closes #197.

cc @Lorilatschki

Then you should be able to use:

@@ -1 +1 @@
- inlineHeader = """Copyright © {{attrs.git_file_created_year if attrs.git_file_created_year else attrs.disk_file_created_year}}-{{attrs.git_file_modified_year if attrs.git_file_modified_year else attrs.disk_file_created_year}}."""
+ inlineHeader = """Copyright © {{attrs.git_file_created_year if attrs.git_file_created_year else attrs.disk_file_created_year}}-{{attrs.git_file_modified_year if attrs.git_file_modified_year else attrs.disk_file_modified_year}}."""

Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
@Lorilatschki

Copy link
Copy Markdown
Contributor

The question is, in the mentioned usecase, where the file is locally changed, the attrs.git_file_modified_year exist, so the attrs.disk_file_modified_year will not be used, right?

@tisonkun

tisonkun commented Jan 9, 2026

Copy link
Copy Markdown
Member Author

That's correct. Do you logically want a max(attrs.git_file_modified_year, attrs.disk_file_modified_year)?

I think we can implement it with minijinja, whether it's an upstream function or we can register one.

Signed-off-by: tison <wander4096@gmail.com>
@@ -1 +1,2 @@
Copyright {{attrs.git_file_created_year if attrs.git_file_created_year else attrs.disk_file_created_year }} No newline at end of file
Copyright {{attrs.git_file_created_year if attrs.git_file_created_year else attrs.disk_file_created_year }}
Modified {{[attrs.git_modified_year, attrs.disk_file_modified_year] | max}} No newline at end of file

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

If max is what you need, you can try out this example.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sounds as it could work. Will try it later and give you feedback.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Emm .. I think it may not work because all mtime locally would be the very late time after you clone the files.

So for a new cloned local copy, it would be then all "this year".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Let me think of it. The requirement is to track all modified files by VCS, but use the mtime from the local FS.

I need some time to consider what is the proper filter and extract way.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Perhaps patching git::resolve_file_attrs to add an attrs.git_dirty_file_modified_year, and then:

{{ attrs.git_dirty_file_modified_year if attrs.git_dirty_file_modified_year else attrs.git_file_modified_year }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think that would fit. So in case the file is not changed locally, attrs.git_dirty_file_modified_year will not be set. In case it is changed locally, it will get the current year.

Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
@tisonkun

tisonkun commented Jan 9, 2026

Copy link
Copy Markdown
Member Author

@Lorilatschki updated.

I finally chose a different approach - just override the attrs.git_file_created_year and attrs.git_file_modified_year attributes as if the dirty file were committed. This should always be what users want.

Signed-off-by: tison <wander4096@gmail.com>
Comment thread fmt/src/git.rs
Comment on lines +174 to 182
// process dirty working tree
let status_platform = repo.status(gix::progress::Discard)?;
let status_iter = status_platform.into_index_worktree_iter(None)?;
let now = gix::date::Time::now_local_or_utc();
for item in status_iter {
let item = item.context("failed to check git status item")?;
let rel_path = item.rela_path();
update_attrs(rel_path, now, current_username.as_str());
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

TIL for implementing #199 (comment).

cc @Byron in case this is not the best practice.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There also is status_platform.into_iter() (or something more general) to get the changes that were added to .git/index as well. The current version doesn't get all changes git status would show.

Otherwise this would be the way the paths of changed items.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for your explaination!

I can see the alternative method returns an extra TreeIndex result. But I'm always using linear commit history, so I'm not quite familiar with the difference. Is there some reference I can use to understand what those extra indices are?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks! IIUC it means into_iter would properly include those file changed after git add . while into_index_worktree_iter only includes those files changed but yet to be added (in the working tree, not in the index).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, that's it.

Comment thread fmt/src/git.rs
Comment on lines +108 to +111
let current_username = match repo.committer() {
Some(Ok(username)) => username.name.to_string(),
_ => "<unknown>".to_string(),
};

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

cc @Byron ditto preparing the "default author" for dirty changes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can do it like this and it's probably easiest as well, as long as you don't find yourself duplicating the logic to deal with an unset committer. In that case, fallbacks for missing committers can be set upon opening the Gix repository.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thank you!

@Lorilatschki

Copy link
Copy Markdown
Contributor

So if I understand it correctly, this will fix the behavior without any adaption on our site except the new version which contains this change, right?

@tisonkun

tisonkun commented Jan 9, 2026

Copy link
Copy Markdown
Member Author

So if I understand it correctly, this will fix the behavior without any adaption on our site except the new version which contains this change, right?

Yes. You can test it with cargo install --path path-to-hawkeye for testing locally.

@Lorilatschki

Copy link
Copy Markdown
Contributor

So if I understand it correctly, this will fix the behavior without any adaption on our site except the new version which contains this change, right?

Yes. You can test it with cargo install --path path-to-hawkeye for testing locally.

Will test it locally and give you feedback if it works. In any case, we should add a test to verify that the 2 attributes behave as expected in case the are change locally.

@Lorilatschki

Lorilatschki commented Jan 9, 2026

Copy link
Copy Markdown
Contributor

Have tested both scenarios with the local installation of your branch support-disk_file_modified_year.

  1. Adding a new file and running hawkeye format creates 2026-2026 as expected
  2. Changing an existing file with the header 2024-2025 and running hawkeye format creates 2024-2026 as expected.

@tisonkun

tisonkun commented Jan 9, 2026

Copy link
Copy Markdown
Member Author

Thank you. I tested it locally as well.

I'm going to refactor the integration tests with trycmd instead of Python script then add more test cases.

@tisonkun
tisonkun merged commit fc27a4a into main Jan 9, 2026
17 checks passed
@tisonkun
tisonkun deleted the support-disk_file_modified_year branch January 9, 2026 23:48
@tisonkun tisonkun changed the title feat: support attrs.disk_file_modified_year feat: overwrite git attrs with dirty status Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Option to tell hawkeye to take care of local changes for hawkeye format

3 participants