Skip to content
Open
Changes from 2 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
66 changes: 55 additions & 11 deletions src/file-manager/fm-icon-container.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
Author: Michael Meeks <michael@ximian.com>
*/
#include <config.h>
#include <stdlib.h>
Comment thread
vkareh marked this conversation as resolved.
Outdated
#include <string.h>

#include <glib/gi18n.h>
Expand Down Expand Up @@ -296,18 +297,26 @@ fm_icon_container_get_icon_text_attribute_names (CajaIconContainer *container,
return attributes;
}

typedef enum {
GITDIR_STANDARD,
GITDIR_WORKTREE,
GITDIR_SUBMODULE,
} GitdirType;

/**
* Parse a .git directory/file to determine repository branch name
**/
static char *
get_git_branch (const char *git_path) {
gchar *resolved_gitdir = NULL;
gchar *head_content = NULL;
gchar *branch_name = NULL;
gchar *head_path = NULL;
const gchar *effective_gitdir;

if (g_file_test (git_path, G_FILE_TEST_IS_REGULAR))
{
/* It's a file, thus we are probably dealing with a submodule, so read it to resolve the real git dir */
/* It's a file — submodule or worktree. Read it to resolve the real git dir. */
Comment thread
vkareh marked this conversation as resolved.
Outdated
gchar *contents = NULL;
if (g_file_get_contents (git_path, &contents, NULL, NULL) && contents)
{
Expand All @@ -316,19 +325,49 @@ get_git_branch (const char *git_path) {
{
size_t git_dir_prefix_len = strlen (git_dir_prefix);
gchar *relative = g_strstrip (contents + git_dir_prefix_len);
gchar *base = g_path_get_dirname (git_path);
g_free (git_path);
git_path = g_build_filename (base, relative, NULL);
g_free (base);
if (!g_path_is_absolute (relative))
{
gchar *base = g_path_get_dirname (git_path);
gchar *joined = g_build_filename (base, relative, NULL);
g_free (base);
/* realpath resolves ../ components; returns NULL if path does not exist */
char *rp = realpath (joined, NULL);
g_free (joined);
if (rp != NULL)
{
resolved_gitdir = g_strdup (rp);
free (rp);
}
Comment thread
vkareh marked this conversation as resolved.
Outdated
}
else
{
resolved_gitdir = g_strdup (relative);
}
}
g_free (contents);
}
effective_gitdir = resolved_gitdir; /* may be NULL if path absent on disk */
}
else
{
effective_gitdir = git_path;
}

/* Extract the current git branch name of the repository from file HEAD within .git directory */
if (g_file_test (git_path, G_FILE_TEST_IS_DIR))
/* Classify the git context, then extract branch name from HEAD */
if (effective_gitdir != NULL && g_file_test (effective_gitdir, G_FILE_TEST_IS_DIR))
{
head_path = g_build_filename (git_path, "HEAD", NULL);
GitdirType gitdir_type;
if (strstr (effective_gitdir, ".git/worktrees/") != NULL)
gitdir_type = GITDIR_WORKTREE;
else if (strstr (effective_gitdir, ".git/modules/") != NULL)
gitdir_type = GITDIR_SUBMODULE;
Comment thread
vkareh marked this conversation as resolved.
Outdated
else
gitdir_type = GITDIR_STANDARD;

const char *suffix = (gitdir_type == GITDIR_WORKTREE) ? " ⎇" :
(gitdir_type == GITDIR_SUBMODULE) ? " ⊂" : "";
Comment on lines +358 to +359

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would these render in all systems, or would it show a tofu box instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I do not know, and it is beyond my scope to find out. I went with it because it looks good compared to the alternative options considered. If there is downstream feedback about it being a problem, it can be revisited later. In possible cases of them not rendering, at least it should fail safe with the tofu box.

Run-time determination of the available character set is beyond the scope of the feature introductory effort.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sure, but I expect more due diligence than "out of scope" when it's actually the purpose of the feature you're submitting.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Until the possibility of rendering issues being reported, the current implementation should fail safe. If such is reported further investigations can be undertaken.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Until the possibility of rendering issues being reported, the current implementation should fail safe. If such is reported further investigations can be undertaken.

You're proposing a "fix after merge" solution to a "test before merge" problem.

No.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we do "fix after merge" or even "test after merge" with code AI played any role in, people will lose trust in MATE. Bad enough to do that with our own code but it we do that with AI we break faith with millions who do not trust AI.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have already tested it and it works perfectly. What I am proposing is that if an issue is identified, then it shall be investigated - just like with any other software artefact.

Clearly.

I was going by what you said earlier:

I do not know, and it is beyond my scope to find out.

If you've tested this in a variety of standard fonts and they all work consistently, then that's the "due diligence" part I'm referring to.

My original review question was:

Would these render in all systems, or would it show a tofu box instead?

Seems like you have a reasonable answer to that question then. You've tested across a variety of setups and did not encounter tofu boxes, yes?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What happens if an intentionally bad font is thrown at it? If I were an attacker that's one of the things I would try. "Tofu boxes" if this is what I think it is would be OK, a segfault would not be.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correct. I'm just disclosing that upon looking at the list of distributions on the Caja GitHub page https://github.com/mate-desktop/caja - I have not tried on many of these. For example, I'm not about to try configuring a build system under Cygwin in order to test for these rendering as tofo boxes or not. Another option may be to have the strings mapped into the translation system, but then I would think this is not really an issue of language translation, but rather of font support on all possible systems. When I implemented the original feature, I ended up spending way more time on the string translations than I did on the underlying code. And even then, I wasn't able to cover all the currently supported languages.

@lukefromdc lukefromdc Jun 8, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

To test on all distros is not what I'm asking and is certainly beyond my own capacity with no landline and no VM experience. Rather I would favor testing with a variety known good and then some known bad fonts to see what happens. That should cover most cases.

Same basic idea as testing a passphrase handling gui with a good passphrase, then a bad one, and finally with a whole page of text cut and pasted in while running from terminal. The last looks for buffer overflows in that case.


head_path = g_build_filename (effective_gitdir, "HEAD", NULL);
if (g_file_get_contents (head_path, &head_content, NULL, NULL))
{
g_strstrip (head_content);
Expand All @@ -337,19 +376,24 @@ get_git_branch (const char *git_path) {
gchar **parts = g_strsplit (head_content, "/", -1);
if (parts != NULL)
{
branch_name = g_strdup (parts[g_strv_length(parts) - 1]);
g_strchomp (branch_name);
gchar *raw = g_strdup (parts[g_strv_length(parts) - 1]);
g_strchomp (raw);
branch_name = g_strdup_printf ("%s%s", raw, suffix);
g_free (raw);
g_strfreev (parts);
}
}
else
{
/* Repository is in a detached HEAD state */
branch_name = g_strdup_printf (_("detached: %.7s"), head_content);
gchar *base_name = g_strdup_printf (_("detached: %.7s"), head_content);
branch_name = g_strdup_printf ("%s%s", base_name, suffix);
g_free (base_name);
}
}
}

g_free (resolved_gitdir);
g_free (head_content);
g_free (head_path);

Expand Down
Loading