Add git integration

This commit is contained in:
savalet
2025-05-21 23:53:44 +02:00
parent 60a65c20d7
commit c37a8f2b47
3 changed files with 128 additions and 4 deletions

90
src/git.c Normal file
View File

@@ -0,0 +1,90 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "git.h"
static
int read_head_branch(char *branch, size_t size)
{
FILE *f = fopen(".git/HEAD", "r");
char line[MAX_LINE];
if (!f)
return -1;
if (!fgets(line, sizeof(line), f)) {
fclose(f);
return -1;
}
fclose(f);
if (strncmp(line, "ref: refs/heads/", 16) != 0)
return -1;
strncpy(branch, line + 16, size - 1);
branch[strcspn(branch, "\n")] = '\0';
return 0;
}
static
int read_git_ref(const char *path, char *hash, size_t size)
{
FILE *f = fopen(path, "r");
if (!f)
return -1;
if (!fgets(hash, size, f)) {
fclose(f);
return -1;
}
fclose(f);
hash[strcspn(hash, "\n")] = '\0';
return 0;
}
static
int compare_hashes(const char *local, const char *remote)
{
if (strcmp(local, remote) == 0)
return 0;
return 1;
}
static
int analyze_divergence(git_status_t *status)
{
if (compare_hashes(status->local_hash, status->remote_hash) == 0) {
status->ahead = 0;
status->behind = 0;
} else {
status->ahead = 1;
status->behind = 1;
}
return 0;
}
bool get_git_status(git_status_t *status)
{
char local_path[256];
char remote_path[256];
if (read_head_branch(status->branch, sizeof(status->branch)) != 0)
return false;
snprintf(local_path, sizeof(local_path),
".git/refs/heads/%s", status->branch);
snprintf(remote_path, sizeof(remote_path),
".git/refs/remotes/origin/%s", status->branch);
if (read_git_ref(local_path, status->local_hash,
sizeof(status->local_hash)) != 0)
return false;
if (read_git_ref(remote_path, status->remote_hash,
sizeof(status->remote_hash)) != 0)
return false;
analyze_divergence(status);
return true;
}

23
src/git.h Normal file
View File

@@ -0,0 +1,23 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#ifndef GIT_H
#define GIT_H
#define MAX_LINE 256
#define MAX_BRANCH 128
#define HASH_LEN 41
typedef struct {
char branch[MAX_BRANCH];
char local_hash[HASH_LEN];
char remote_hash[HASH_LEN];
int ahead;
int behind;
} git_status_t;
bool get_git_status(git_status_t *status);
#endif /* GIT_H */

View File

@@ -10,12 +10,13 @@
#include <termios.h>
#include <unistd.h>
#include "ast.h"
#include "common.h"
#include "debug.h"
#include "git.h"
#include "repl.h"
#include "repl/key_handler.h"
#include "u_str.h"
#include "visitor.h"
#include "vt100_esc_codes.h"
const key_handler_t KEY_HANDLERS[] = {
@@ -53,20 +54,30 @@ void print_second_shell_prompt(exec_ctx_t *ec)
}
}
static
void print_git_prompt(git_status_t *gs)
{
if (!gs->ahead && !gs->behind)
printf(BLUE " [" RED "%s" BLUE "] " RESET "-", gs->branch);
}
static
void print_prompt(env_t *env_ptr, char *hostname, exec_ctx_t *ec)
{
char const *username = get_env_value(env_ptr, "USER");
git_status_t gs = {0};
if (username == nullptr)
username = "?";
printf(BLUE PROMPT_HEADER GREEN "%s" RESET "@" CYAN "%s" BLUE "] "
RESET "-" BLUE " [" RESET "%s" BLUE
"] " RESET "-" BLUE " [" YELLOW "%d" BLUE
"]\n└─[" PURPLE "%s%s" BLUE "] " RESET,
"] " RESET "-",
username,
hostname,
get_env_value(env_ptr, "PWD"),
get_env_value(env_ptr, "PWD"));
if (get_git_status(&gs))
print_git_prompt(&gs);
printf(BLUE " [" YELLOW "%d" BLUE "]\n└─[" PURPLE "%s%s" BLUE "] " RESET,
ec->history_command->sz + 1,
ec->history->last_exit_code == 0 ? "" : RED,
strcmp(username, "root") == 0 ? "#" : "$");