mirror of
https://github.com/Savapitech/42sh.git
synced 2026-03-18 21:50:35 +01:00
Add git integration
This commit is contained in:
90
src/git.c
Normal file
90
src/git.c
Normal 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
23
src/git.h
Normal 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 */
|
||||||
@@ -10,12 +10,13 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "ast.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "git.h"
|
||||||
#include "repl.h"
|
#include "repl.h"
|
||||||
#include "repl/key_handler.h"
|
#include "repl/key_handler.h"
|
||||||
#include "u_str.h"
|
#include "u_str.h"
|
||||||
#include "visitor.h"
|
|
||||||
#include "vt100_esc_codes.h"
|
#include "vt100_esc_codes.h"
|
||||||
|
|
||||||
const key_handler_t KEY_HANDLERS[] = {
|
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
|
static
|
||||||
void print_prompt(env_t *env_ptr, char *hostname, exec_ctx_t *ec)
|
void print_prompt(env_t *env_ptr, char *hostname, exec_ctx_t *ec)
|
||||||
{
|
{
|
||||||
char const *username = get_env_value(env_ptr, "USER");
|
char const *username = get_env_value(env_ptr, "USER");
|
||||||
|
git_status_t gs = {0};
|
||||||
|
|
||||||
if (username == nullptr)
|
if (username == nullptr)
|
||||||
username = "?";
|
username = "?";
|
||||||
printf(BLUE PROMPT_HEADER GREEN "%s" RESET "@" CYAN "%s" BLUE "] "
|
printf(BLUE PROMPT_HEADER GREEN "%s" RESET "@" CYAN "%s" BLUE "] "
|
||||||
RESET "-" BLUE " [" RESET "%s" BLUE
|
RESET "-" BLUE " [" RESET "%s" BLUE
|
||||||
"] " RESET "-" BLUE " [" YELLOW "%d" BLUE
|
"] " RESET "-",
|
||||||
"]\n└─[" PURPLE "%s%s" BLUE "] " RESET,
|
|
||||||
username,
|
username,
|
||||||
hostname,
|
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_command->sz + 1,
|
||||||
ec->history->last_exit_code == 0 ? "" : RED,
|
ec->history->last_exit_code == 0 ? "" : RED,
|
||||||
strcmp(username, "root") == 0 ? "#" : "$");
|
strcmp(username, "root") == 0 ? "#" : "$");
|
||||||
|
|||||||
Reference in New Issue
Block a user