mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-22 05:14:59 +00:00
feat: implement Co-authored-by attribution option
This commit is contained in:
parent
a5327af5e9
commit
b22c9b8542
2 changed files with 89 additions and 40 deletions
|
@ -125,7 +125,41 @@ class GitRepo:
|
||||||
commit_message = self.get_commit_message(diffs, context)
|
commit_message = self.get_commit_message(diffs, context)
|
||||||
|
|
||||||
commit_message_trailer = ""
|
commit_message_trailer = ""
|
||||||
|
attribute_author = self.attribute_author
|
||||||
|
attribute_committer = self.attribute_committer
|
||||||
|
attribute_commit_message_author = self.attribute_commit_message_author
|
||||||
|
attribute_commit_message_committer = self.attribute_commit_message_committer
|
||||||
|
attribute_co_authored_by = False # Default if coder or args not available
|
||||||
|
|
||||||
|
if coder and hasattr(coder, "args"):
|
||||||
|
attribute_author = coder.args.attribute_author
|
||||||
|
attribute_committer = coder.args.attribute_committer
|
||||||
|
attribute_commit_message_author = coder.args.attribute_commit_message_author
|
||||||
|
attribute_commit_message_committer = coder.args.attribute_commit_message_committer
|
||||||
|
attribute_co_authored_by = coder.args.attribute_co_authored_by
|
||||||
|
|
||||||
if aider_edits:
|
if aider_edits:
|
||||||
|
# Add Co-authored-by trailer if configured
|
||||||
|
if attribute_co_authored_by:
|
||||||
|
model_name = "unknown-model"
|
||||||
|
if coder and hasattr(coder, "main_model") and coder.main_model.name:
|
||||||
|
model_name = coder.main_model.name
|
||||||
|
commit_message_trailer = (
|
||||||
|
f"\n\nCo-authored-by: aider ({model_name}) <noreply@aider.dev>"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Prefix commit message if configured
|
||||||
|
if attribute_commit_message_author or attribute_commit_message_committer:
|
||||||
|
commit_message = "aider: " + commit_message
|
||||||
|
|
||||||
|
# Prepare author/committer modification flags (used later)
|
||||||
|
use_attribute_author = attribute_author
|
||||||
|
use_attribute_committer = attribute_committer
|
||||||
|
else:
|
||||||
|
# Don't modify author/committer/message for non-aider edits
|
||||||
|
use_attribute_author = False
|
||||||
|
use_attribute_committer = self.attribute_committer # Keep committer modification for non-aider edits if configured
|
||||||
|
|
||||||
# Use coder.args if available, otherwise default to config/defaults
|
# Use coder.args if available, otherwise default to config/defaults
|
||||||
attribute_author = (
|
attribute_author = (
|
||||||
coder.args.attribute_author
|
coder.args.attribute_author
|
||||||
|
@ -143,29 +177,6 @@ class GitRepo:
|
||||||
else self.attribute_commit_message_author
|
else self.attribute_commit_message_author
|
||||||
)
|
)
|
||||||
attribute_commit_message_committer = (
|
attribute_commit_message_committer = (
|
||||||
coder.args.attribute_commit_message_committer
|
|
||||||
if coder and hasattr(coder, "args")
|
|
||||||
else self.attribute_commit_message_committer
|
|
||||||
)
|
|
||||||
attribute_co_authored_by = (
|
|
||||||
coder.args.attribute_co_authored_by
|
|
||||||
if coder and hasattr(coder, "args")
|
|
||||||
else False # Default to False if not found
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add Co-authored-by trailer if configured
|
|
||||||
if attribute_co_authored_by:
|
|
||||||
model_name = "unknown-model"
|
|
||||||
if coder and hasattr(coder, "main_model") and coder.main_model.name:
|
|
||||||
model_name = coder.main_model.name
|
|
||||||
commit_message_trailer = (
|
|
||||||
f"\n\nCo-authored-by: aider ({model_name}) <noreply@aider.dev>"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Prefix commit message if configured
|
|
||||||
if attribute_commit_message_author or attribute_commit_message_committer:
|
|
||||||
commit_message = "aider: " + commit_message
|
|
||||||
|
|
||||||
if not commit_message:
|
if not commit_message:
|
||||||
commit_message = "(no commit message provided)"
|
commit_message = "(no commit message provided)"
|
||||||
|
|
||||||
|
@ -192,22 +203,11 @@ class GitRepo:
|
||||||
original_author_name_env = os.environ.get("GIT_AUTHOR_NAME")
|
original_author_name_env = os.environ.get("GIT_AUTHOR_NAME")
|
||||||
committer_name = f"{original_user_name} (aider)"
|
committer_name = f"{original_user_name} (aider)"
|
||||||
|
|
||||||
# Use coder.args if available, otherwise default to config/defaults
|
# Apply author/committer modifications based on flags determined earlier
|
||||||
use_attribute_committer = (
|
|
||||||
coder.args.attribute_committer
|
|
||||||
if coder and hasattr(coder, "args")
|
|
||||||
else self.attribute_committer
|
|
||||||
)
|
|
||||||
use_attribute_author = (
|
|
||||||
coder.args.attribute_author
|
|
||||||
if coder and hasattr(coder, "args")
|
|
||||||
else self.attribute_author
|
|
||||||
)
|
|
||||||
|
|
||||||
if use_attribute_committer:
|
if use_attribute_committer:
|
||||||
os.environ["GIT_COMMITTER_NAME"] = committer_name
|
os.environ["GIT_COMMITTER_NAME"] = committer_name
|
||||||
|
|
||||||
if aider_edits and use_attribute_author:
|
if use_attribute_author: # Already checks for aider_edits implicitly
|
||||||
os.environ["GIT_AUTHOR_NAME"] = committer_name
|
os.environ["GIT_AUTHOR_NAME"] = committer_name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -225,7 +225,7 @@ class GitRepo:
|
||||||
elif "GIT_COMMITTER_NAME" in os.environ:
|
elif "GIT_COMMITTER_NAME" in os.environ:
|
||||||
del os.environ["GIT_COMMITTER_NAME"]
|
del os.environ["GIT_COMMITTER_NAME"]
|
||||||
|
|
||||||
if aider_edits and use_attribute_author:
|
if use_attribute_author: # Already checks for aider_edits implicitly
|
||||||
if original_author_name_env is not None:
|
if original_author_name_env is not None:
|
||||||
os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
|
os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
|
||||||
elif "GIT_AUTHOR_NAME" in os.environ:
|
elif "GIT_AUTHOR_NAME" in os.environ:
|
||||||
|
|
|
@ -229,10 +229,11 @@ class TestRepo(unittest.TestCase):
|
||||||
raw_repo.git.commit("-m", "initial commit")
|
raw_repo.git.commit("-m", "initial commit")
|
||||||
|
|
||||||
# Mock coder args
|
# Mock coder args
|
||||||
|
# Mock coder args: Co-authored-by enabled, author/committer modification disabled
|
||||||
mock_coder = MagicMock()
|
mock_coder = MagicMock()
|
||||||
mock_coder.args.attribute_co_authored_by = True
|
mock_coder.args.attribute_co_authored_by = True
|
||||||
mock_coder.args.attribute_author = None # Explicitly None to test override
|
mock_coder.args.attribute_author = False # Explicitly disable name modification
|
||||||
mock_coder.args.attribute_committer = None # Explicitly None to test override
|
mock_coder.args.attribute_committer = False # Explicitly disable name modification
|
||||||
mock_coder.args.attribute_commit_message_author = False
|
mock_coder.args.attribute_commit_message_author = False
|
||||||
mock_coder.args.attribute_commit_message_committer = False
|
mock_coder.args.attribute_commit_message_committer = False
|
||||||
# Set the model name correctly on the nested mock
|
# Set the model name correctly on the nested mock
|
||||||
|
@ -255,6 +256,51 @@ class TestRepo(unittest.TestCase):
|
||||||
self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
|
self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
|
||||||
self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
|
self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
|
||||||
|
|
||||||
|
def test_commit_with_co_authored_by_and_name_modification(self):
|
||||||
|
# Test scenario where Co-authored-by is true AND author/committer modification is also true (default)
|
||||||
|
# Cleanup of the git temp dir explodes on windows
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
return
|
||||||
|
|
||||||
|
with GitTemporaryDirectory():
|
||||||
|
# new repo
|
||||||
|
raw_repo = git.Repo()
|
||||||
|
raw_repo.config_writer().set_value("user", "name", "Test User").release()
|
||||||
|
raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
|
||||||
|
|
||||||
|
# add a file and commit it
|
||||||
|
fname = Path("file.txt")
|
||||||
|
fname.touch()
|
||||||
|
raw_repo.git.add(str(fname))
|
||||||
|
raw_repo.git.commit("-m", "initial commit")
|
||||||
|
|
||||||
|
# Mock coder args: Co-authored-by enabled, author/committer modification enabled (default)
|
||||||
|
mock_coder = MagicMock()
|
||||||
|
mock_coder.args.attribute_co_authored_by = True
|
||||||
|
mock_coder.args.attribute_author = True # Explicitly enable (or rely on default)
|
||||||
|
mock_coder.args.attribute_committer = True # Explicitly enable (or rely on default)
|
||||||
|
mock_coder.args.attribute_commit_message_author = False
|
||||||
|
mock_coder.args.attribute_commit_message_committer = False
|
||||||
|
# Set the model name correctly on the nested mock
|
||||||
|
mock_coder.main_model = MagicMock()
|
||||||
|
mock_coder.main_model.name = "gpt-test-combo"
|
||||||
|
|
||||||
|
|
||||||
|
io = InputOutput()
|
||||||
|
git_repo = GitRepo(io, None, None)
|
||||||
|
|
||||||
|
# commit a change with aider_edits=True and combo flags
|
||||||
|
fname.write_text("new content combo")
|
||||||
|
git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider combo edit")
|
||||||
|
|
||||||
|
# check the commit message and author/committer
|
||||||
|
commit = raw_repo.head.commit
|
||||||
|
self.assertIn("Co-authored-by: aider (gpt-test-combo) <noreply@aider.dev>", commit.message)
|
||||||
|
self.assertEqual(commit.message.splitlines()[0], "Aider combo edit")
|
||||||
|
self.assertEqual(commit.author.name, "Test User (aider)") # Should BE modified
|
||||||
|
self.assertEqual(commit.committer.name, "Test User (aider)") # Should BE modified
|
||||||
|
|
||||||
|
|
||||||
def test_commit_without_co_authored_by(self):
|
def test_commit_without_co_authored_by(self):
|
||||||
# Cleanup of the git temp dir explodes on windows
|
# Cleanup of the git temp dir explodes on windows
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
|
@ -279,7 +325,10 @@ class TestRepo(unittest.TestCase):
|
||||||
mock_coder.args.attribute_committer = True
|
mock_coder.args.attribute_committer = True
|
||||||
mock_coder.args.attribute_commit_message_author = False
|
mock_coder.args.attribute_commit_message_author = False
|
||||||
mock_coder.args.attribute_commit_message_committer = False
|
mock_coder.args.attribute_commit_message_committer = False
|
||||||
mock_coder.model.name = "gpt-test"
|
# Set the model name correctly on the nested mock (though not used in this test assertion)
|
||||||
|
mock_coder.main_model = MagicMock()
|
||||||
|
mock_coder.main_model.name = "gpt-test-no-coauthor"
|
||||||
|
|
||||||
|
|
||||||
io = InputOutput()
|
io = InputOutput()
|
||||||
git_repo = GitRepo(io, None, None)
|
git_repo = GitRepo(io, None, None)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue