[PATCH] git-save: improve commit authorship data

Linus Torvalds torvalds at linux-foundation.org
Mon Apr 14 14:41:35 PDT 2014


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Mon, 14 Apr 2014 14:33:46 -0700
Subject: [PATCH] git-save: improve commit authorship data

We used to always just commit as "subsurface at hohndel.org" because
libgit-19 doesn't have the interfaces to do user name lookup.  This does
better if you have libgit-20, using "git_signature_default()" to get the
actual user that does the saving.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---

This tries to use "git_signature_default()" to get user information for 
the commit authorship, but if libgit2 is too old, it falls back on 
creating the data by hand like it used to. But even then we try to 
actually get a real user name and fake email (really just user at hostname, 
not a real email).

However, we do the real user name only on Linux. I assume the same 
getpwuid() approach would work on OSX, but Windows does its own thing. 
However, at least Dirk seems to compile current libgit2 for the OSX and 
Windows binaries, so it simply doesn't matter. On at least Fedora, the 
distro libgit2 is still 0.19 that doesn't have the new interfaces.

 dive.h     |  6 ++++++
 linux.c    | 23 +++++++++++++++++++++++
 macos.c    |  3 +++
 save-git.c | 23 +++++++++++++++++++++--
 windows.c  |  3 +++
 5 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/dive.h b/dive.h
index 89497b75a057..62d57d6ccd59 100644
--- a/dive.h
+++ b/dive.h
@@ -714,6 +714,12 @@ extern const char *saved_git_id;
 extern void clear_git_id(void);
 extern void set_git_id(const struct git_oid *);
 
+struct user_info {
+	const char *name;
+	const char *email;
+};
+
+extern void subsurface_user_info(struct user_info *);
 extern int subsurface_rename(const char *path, const char *newpath);
 extern int subsurface_open(const char *path, int oflags, mode_t mode);
 extern FILE *subsurface_fopen(const char *path, const char *mode);
diff --git a/linux.c b/linux.c
index ea0170dc89f8..03d0bfbf9670 100644
--- a/linux.c
+++ b/linux.c
@@ -2,16 +2,39 @@
 /* implements Linux specific functions */
 #include "dive.h"
 #include "display.h"
+#include "membuffer.h"
 #include <string.h>
 #include <sys/types.h>
 #include <dirent.h>
 #include <fnmatch.h>
 #include <stdio.h>
 #include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
 
 const char system_divelist_default_font[] = "Sans";
 const int system_divelist_default_font_size = 8;
 
+void subsurface_user_info(struct user_info *user)
+{
+	struct passwd *pwd = getpwuid(getuid());
+	const char *username = getenv("USER");
+
+	if (pwd) {
+		if (pwd->pw_gecos && *pwd->pw_gecos)
+			user->name = pwd->pw_gecos;
+		if (!username)
+			username = pwd->pw_name;
+	}
+	if (username && *username) {
+		const char hostname[64];
+		struct membuffer mb = { 0 };
+		gethostname(hostname, sizeof(hostname));
+		put_format(&mb, "%s@%s", username, hostname);
+		user->email = mb_cstring(&mb);
+	}
+}
+
 const char *system_default_filename(void)
 {
 	const char *home, *user;
diff --git a/macos.c b/macos.c
index 19ce9e89dcd8..25d6fd73f373 100644
--- a/macos.c
+++ b/macos.c
@@ -13,6 +13,9 @@
 #include <fcntl.h>
 #include <dirent.h>
 
+void subsurface_user_info(struct user_info *info)
+{ /* Nothing, let's use libgit2-20 on MacOS */ }
+
 /* macos defines CFSTR to create a CFString object from a constant,
  * but no similar macros if a C string variable is supposed to be
  * the argument. We add this here (hardcoding the default allocator
diff --git a/save-git.c b/save-git.c
index 2e8b608f8160..76175a1974d5 100644
--- a/save-git.c
+++ b/save-git.c
@@ -815,6 +815,24 @@ static int update_git_checkout(git_repository *repo, git_object *parent, git_tre
 	return git_checkout_tree(repo, (git_object *) tree, &opts);
 }
 
+static int get_authorship(git_repository *repo, git_signature **authorp)
+{
+#if LIBGIT2_VER_MAJOR || LIBGIT2_VER_MINOR >= 20
+	return git_signature_default(authorp, repo);
+#else
+	/* Default name information, with potential OS overrides */
+	struct user_info user = {
+		.name = "Subsurface",
+		.email = "subsurace at hohndel.org"
+	};
+
+	subsurface_user_info(&user);
+
+	/* git_signature_default() is too recent */
+	return git_signature_now(authorp, user.name, user.email);
+#endif
+}
+
 static int create_new_commit(git_repository *repo, const char *branch, git_oid *tree_id)
 {
 	int ret;
@@ -853,8 +871,7 @@ static int create_new_commit(git_repository *repo, const char *branch, git_oid *
 	if (git_tree_lookup(&tree, repo, tree_id))
 		return report_error("Could not look up newly created tree");
 
-	/* git_signature_default() is too recent */
-	if (git_signature_now(&author, "Subsurface", "subsurface at hohndel.org"))
+	if (get_authorship(repo, &author))
 		return report_error("No user name configuration in git repo");
 
 	/* If the parent commit has the same tree ID, do not create a new commit */
@@ -897,6 +914,8 @@ static int create_new_commit(git_repository *repo, const char *branch, git_oid *
 		return report_error("Failed to update branch '%s'", branch);
 	set_git_id(&commit_id);
 
+	git_signature_free(author);
+
 	return 0;
 }
 
diff --git a/windows.c b/windows.c
index 5a7707108877..fbc8788a00b9 100644
--- a/windows.c
+++ b/windows.c
@@ -14,6 +14,9 @@
 const char system_divelist_default_font[] = "Sans";
 const int system_divelist_default_font_size = 8;
 
+void subsurface_user(struct user_info *user)
+{ /* Encourage use of at least libgit2-0.20 */ }
+
 const char *system_default_filename(void)
 {
 	char datapath[MAX_PATH];
-- 
1.9.0




More information about the subsurface mailing list