|
5 | 5 | #include "worktree.h"
|
6 | 6 | #include "dir.h"
|
7 | 7 | #include "wt-status.h"
|
| 8 | +#include "config.h" |
8 | 9 |
|
9 | 10 | void free_worktrees(struct worktree **worktrees)
|
10 | 11 | {
|
@@ -826,3 +827,75 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath,
|
826 | 827 | *wtpath = path;
|
827 | 828 | return 0;
|
828 | 829 | }
|
| 830 | + |
| 831 | +static int move_config_setting(const char *key, const char *value, |
| 832 | + const char *from_file, const char *to_file) |
| 833 | +{ |
| 834 | + if (git_config_set_in_file_gently(to_file, key, value)) |
| 835 | + return error(_("unable to set %s in '%s'"), key, to_file); |
| 836 | + if (git_config_set_in_file_gently(from_file, key, NULL)) |
| 837 | + return error(_("unable to unset %s in '%s'"), key, from_file); |
| 838 | + return 0; |
| 839 | +} |
| 840 | + |
| 841 | +int init_worktree_config(struct repository *r) |
| 842 | +{ |
| 843 | + int res = 0; |
| 844 | + int bare = 0; |
| 845 | + struct config_set cs = { { 0 } }; |
| 846 | + const char *core_worktree; |
| 847 | + char *common_config_file; |
| 848 | + char *main_worktree_file; |
| 849 | + |
| 850 | + /* |
| 851 | + * If the extension is already enabled, then we can skip the |
| 852 | + * upgrade process. |
| 853 | + */ |
| 854 | + if (repository_format_worktree_config) |
| 855 | + return 0; |
| 856 | + if ((res = git_config_set_gently("extensions.worktreeConfig", "true"))) |
| 857 | + return error(_("failed to set extensions.worktreeConfig setting")); |
| 858 | + |
| 859 | + common_config_file = xstrfmt("%s/config", r->commondir); |
| 860 | + main_worktree_file = xstrfmt("%s/config.worktree", r->commondir); |
| 861 | + |
| 862 | + git_configset_init(&cs); |
| 863 | + git_configset_add_file(&cs, common_config_file); |
| 864 | + |
| 865 | + /* |
| 866 | + * If core.bare is true in the common config file, then we need to |
| 867 | + * move it to the main worktree's config file or it will break all |
| 868 | + * worktrees. If it is false, then leave it in place because it |
| 869 | + * _could_ be negating a global core.bare=true. |
| 870 | + */ |
| 871 | + if (!git_configset_get_bool(&cs, "core.bare", &bare) && bare) { |
| 872 | + if ((res = move_config_setting("core.bare", "true", |
| 873 | + common_config_file, |
| 874 | + main_worktree_file))) |
| 875 | + goto cleanup; |
| 876 | + } |
| 877 | + /* |
| 878 | + * If core.worktree is set, then the main worktree is located |
| 879 | + * somewhere different than the parent of the common Git dir. |
| 880 | + * Relocate that value to avoid breaking all worktrees with this |
| 881 | + * upgrade to worktree config. |
| 882 | + */ |
| 883 | + if (!git_configset_get_value(&cs, "core.worktree", &core_worktree)) { |
| 884 | + if ((res = move_config_setting("core.worktree", core_worktree, |
| 885 | + common_config_file, |
| 886 | + main_worktree_file))) |
| 887 | + goto cleanup; |
| 888 | + } |
| 889 | + |
| 890 | + /* |
| 891 | + * Ensure that we use worktree config for the remaining lifetime |
| 892 | + * of the current process. |
| 893 | + */ |
| 894 | + repository_format_worktree_config = 1; |
| 895 | + |
| 896 | +cleanup: |
| 897 | + git_configset_clear(&cs); |
| 898 | + free(common_config_file); |
| 899 | + free(main_worktree_file); |
| 900 | + return res; |
| 901 | +} |
0 commit comments