-
Notifications
You must be signed in to change notification settings - Fork 499
DotfileManager: add initial dotfile manager detection #1702
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
"processes", | ||
"packages", | ||
"shell", | ||
"dotfileManager", | ||
"editor", | ||
"display", | ||
"brightness", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Dotfile Manager | ||
|
||
This module attempts to detect the user's dotfile manager. Many [popular dotfile | ||
managers](https://dotfiles.github.io/utilities/) are supported. | ||
|
||
## Supported dotfile managers | ||
|
||
* [Bare git repository](https://www.atlassian.com/git/tutorials/dotfiles) | ||
* [chezmoi](https://chezmoi.io) | ||
* [YADM](https://yadm.io) | ||
|
||
## Unsupported dotfile managers | ||
|
||
### Dotbot | ||
|
||
As [Dotbot](https://github.com/anishathalye/dotbot) is usually imported as a | ||
submodule inside the user's dotfile repository, there is no reliable way to | ||
detect if the user is using it. | ||
|
||
### GNU Stow | ||
|
||
[GNU Stow](https://www.gnu.org/software/stow/) has no standard configuration, so | ||
there is no reliable way to detect if the user is using it. | ||
|
||
### Home manager | ||
|
||
[Home manager](https://github.com/nix-community/home-manager) has no standard | ||
configuration. | ||
|
||
### Mackup | ||
|
||
[Mackup](https://github.com/lra/mackup) does not work on macOS since version 14 | ||
(Sonoma, released September 2023). | ||
|
||
### rcm | ||
|
||
[rcm](https://thoughtbot.github.io/rcm/rcm.7.html) has no standard | ||
configuration. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#include "common/io/io.h" | ||
#include "dotfilemanager.h" | ||
|
||
static bool detectBareGitRepository(FFDotfileManagerResult* result) | ||
{ | ||
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate(); | ||
ffStrbufSet(&fullPath, &instance.state.platform.homeDir); | ||
ffStrbufAppendS(&fullPath, ".git"); | ||
|
||
if (ffPathExists(fullPath.chars, FF_PATHTYPE_DIRECTORY)) { | ||
ffStrbufSetS(&result->name, "bare git repository"); | ||
return true; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should also check if git is installed |
||
return false; | ||
} | ||
|
||
static bool detectChezmoi(FFDotfileManagerResult* result) | ||
{ | ||
FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance.state.platform.dataDirs) | ||
{ | ||
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate(); | ||
ffStrbufSet(&fullPath, dataDir); | ||
ffStrbufAppendS(&fullPath, "chezmoi"); | ||
|
||
if (ffPathExists(fullPath.chars, FF_PATHTYPE_DIRECTORY)) { | ||
ffStrbufSetS(&result->name, "chezmoi"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check if chezmoi command exists |
||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
static bool detectYADM(FFDotfileManagerResult* result) | ||
{ | ||
FF_LIST_FOR_EACH(FFstrbuf, configDir, instance.state.platform.configDirs) | ||
{ | ||
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate(); | ||
ffStrbufSet(&fullPath, configDir); | ||
ffStrbufAppendS(&fullPath, "yadm"); | ||
|
||
if (ffPathExists(fullPath.chars, FF_PATHTYPE_DIRECTORY)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
ffStrbufSetS(&result->name, "yadm"); | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
const char* ffDetectDotfileManager(FFDotfileManagerResult* result) | ||
{ | ||
if (detectBareGitRepository(result)) return NULL; | ||
if (detectChezmoi(result)) return NULL; | ||
if (detectYADM(result)) return NULL; | ||
|
||
return NULL; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
#include "fastfetch.h" | ||
|
||
typedef struct FFDotfileManagerResult | ||
{ | ||
FFstrbuf name; | ||
} FFDotfileManagerResult; | ||
|
||
const char* ffDetectDotfileManager(FFDotfileManagerResult* result); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#include "common/printing.h" | ||
#include "common/jsonconfig.h" | ||
#include "detection/libc/libc.h" | ||
#include "detection/dotfilemanager/dotfilemanager.h" | ||
#include "modules/dotfilemanager/dotfilemanager.h" | ||
#include "util/stringUtils.h" | ||
|
||
void ffPrintDotfileManager(FFDotfileManagerOptions* options) | ||
{ | ||
FFDotfileManagerResult result = { | ||
.name = ffStrbufCreate(), | ||
}; | ||
const char* error = ffDetectDotfileManager(&result); | ||
|
||
if (error) | ||
{ | ||
ffPrintError(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); | ||
return; | ||
} | ||
|
||
if (options->moduleArgs.outputFormat.length == 0) | ||
{ | ||
ffPrintLogoAndKey(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); | ||
ffStrbufWriteTo(&result.name, stdout); | ||
putchar('\n'); | ||
} | ||
else | ||
{ | ||
FF_PRINT_FORMAT_CHECKED(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ | ||
FF_FORMAT_ARG(result.name, "name"), | ||
})); | ||
} | ||
|
||
ffStrbufDestroy(&result.name); | ||
} | ||
|
||
bool ffParseDotfileManagerCommandOptions(FFDotfileManagerOptions* options, const char* key, const char* value) | ||
{ | ||
const char* subKey = ffOptionTestPrefix(key, FF_DOTFILEMANAGER_MODULE_NAME); | ||
if (!subKey) return false; | ||
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) | ||
return true; | ||
|
||
return false; | ||
} | ||
|
||
void ffParseDotfileManagerJsonObject(FFDotfileManagerOptions* options, yyjson_val* module) | ||
{ | ||
yyjson_val *key_, *val; | ||
size_t idx, max; | ||
yyjson_obj_foreach(module, idx, max, key_, val) | ||
{ | ||
const char* key = yyjson_get_str(key_); | ||
if(ffStrEqualsIgnCase(key, "type")) | ||
continue; | ||
|
||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) | ||
continue; | ||
|
||
ffPrintError(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); | ||
} | ||
} | ||
|
||
void ffGenerateDotfileManagerJsonConfig(FFDotfileManagerOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) | ||
{ | ||
__attribute__((__cleanup__(ffDestroyDotfileManagerOptions))) FFDotfileManagerOptions defaultOptions; | ||
ffInitDotfileManagerOptions(&defaultOptions); | ||
|
||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); | ||
} | ||
|
||
void ffGenerateDotfileManagerJsonResult(FF_MAYBE_UNUSED FFDotfileManagerOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) | ||
{ | ||
FFDotfileManagerResult result = { | ||
.name = ffStrbufCreate(), | ||
}; | ||
|
||
const char* error = ffDetectDotfileManager(&result); | ||
|
||
if (error) | ||
{ | ||
yyjson_mut_obj_add_str(doc, module, "error", error); | ||
return; | ||
} | ||
|
||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); | ||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &result.name); | ||
|
||
ffStrbufDestroy(&result.name); | ||
} | ||
|
||
static FFModuleBaseInfo ffModuleInfo = { | ||
.name = FF_DOTFILEMANAGER_MODULE_NAME, | ||
.description = "Print information about the dotfile manager", | ||
.parseCommandOptions = (void*) ffParseDotfileManagerCommandOptions, | ||
.parseJsonObject = (void*) ffParseDotfileManagerJsonObject, | ||
.printModule = (void*) ffPrintDotfileManager, | ||
.generateJsonResult = (void*) ffGenerateDotfileManagerJsonResult, | ||
.generateJsonConfig = (void*) ffGenerateDotfileManagerJsonConfig, | ||
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { | ||
{"Name", "name"}, | ||
})) | ||
}; | ||
|
||
void ffInitDotfileManagerOptions(FFDotfileManagerOptions* options) | ||
{ | ||
options->moduleInfo = ffModuleInfo; | ||
ffOptionInitModuleArg(&options->moduleArgs, ""); | ||
} | ||
|
||
void ffDestroyDotfileManagerOptions(FFDotfileManagerOptions* options) | ||
{ | ||
ffOptionDestroyModuleArg(&options->moduleArgs); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#pragma once | ||
|
||
#include "fastfetch.h" | ||
|
||
#define FF_DOTFILEMANAGER_MODULE_NAME "DotfileManager" | ||
|
||
void ffPrintDotfileManager(FFDotfileManagerOptions* options); | ||
void ffInitDotfileManagerOptions(FFDotfileManagerOptions* options); | ||
void ffDestroyDotfileManagerOptions(FFDotfileManagerOptions* options); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
|
||
// This file will be included in "fastfetch.h", do NOT put unnecessary things here | ||
|
||
#include "common/option.h" | ||
|
||
typedef struct FFDotfileManagerOptions | ||
{ | ||
FFModuleBaseInfo moduleInfo; | ||
FFModuleArgs moduleArgs; | ||
} FFDotfileManagerOptions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is frustrating. As far as I know it's commonly used by Nix community