Skip to content

Commit

Permalink
Merge branch '11.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
杨赫然 committed Jul 16, 2024
2 parents ba9476d + d51591d commit 11d4741
Show file tree
Hide file tree
Showing 23 changed files with 758 additions and 249 deletions.
4 changes: 2 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ endif

MAKE_SERVER = server tools $(MAKE_CONTROLLER) $(MAKE_FUSE)

SUBDIRS = include lib common python $(MAKE_SERVER) doc
SUBDIRS = include lib common python $(MAKE_SERVER) doc scripts

DIST_SUBDIRS = include lib common python server tools controller fuse doc
DIST_SUBDIRS = include lib common python server tools controller fuse doc scripts

INTLTOOL = \
intltool-extract.in \
Expand Down
2 changes: 2 additions & 0 deletions common/branch-mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ notify_repo_update (const char *repo_id, const char *commit_id)
static void
on_branch_updated (SeafBranchManager *mgr, SeafBranch *branch)
{
if (seaf->is_repair)
return;
seaf_repo_manager_update_repo_info (seaf->repo_mgr, branch->repo_id, branch->commit_id);

notify_repo_update(branch->repo_id, branch->commit_id);
Expand Down
199 changes: 179 additions & 20 deletions common/merge-new.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,39 @@ merge_trees_recursive (const char *store_id, int version,
const char *basedir,
MergeOptions *opt);

static const char *
get_nickname_by_modifier (GHashTable *email_to_nickname, const char *modifier)
{
const char *nickname = NULL;

if (!modifier) {
return NULL;
}

nickname = g_hash_table_lookup (email_to_nickname, modifier);
if (nickname) {
return nickname;
}

char *sql = "SELECT nickname from profile_profile WHERE user = ?";
nickname = seaf_db_statement_get_string(seaf->seahub_db, sql, 1, "string", modifier);

if (!nickname) {
nickname = modifier;
}
g_hash_table_insert (email_to_nickname, g_strdup(modifier), g_strdup(nickname));

return nickname;
}

static char *
merge_conflict_filename (const char *store_id, int version,
MergeOptions *opt,
const char *basedir,
const char *filename)
{
char *path = NULL, *modifier = NULL, *conflict_name = NULL;
const char *nickname = NULL;
gint64 mtime;
SeafCommit *commit;

Expand All @@ -46,7 +72,11 @@ merge_conflict_filename (const char *store_id, int version,
seaf_commit_unref (commit);
}

conflict_name = gen_conflict_path (filename, modifier, mtime);
nickname = modifier;
if (seaf->seahub_db)
nickname = get_nickname_by_modifier (opt->email_to_nickname, modifier);

conflict_name = gen_conflict_path (filename, nickname, mtime);

out:
g_free (path);
Expand All @@ -61,6 +91,7 @@ merge_conflict_dirname (const char *store_id, int version,
const char *dirname)
{
char *modifier = NULL, *conflict_name = NULL;
const char *nickname = NULL;
SeafCommit *commit;

commit = seaf_commit_manager_get_commit (seaf->commit_mgr,
Expand All @@ -74,38 +105,90 @@ merge_conflict_dirname (const char *store_id, int version,
modifier = g_strdup(commit->creator_name);
seaf_commit_unref (commit);

conflict_name = gen_conflict_path (dirname, modifier, (gint64)time(NULL));
nickname = modifier;
if (seaf->seahub_db)
nickname = get_nickname_by_modifier (opt->email_to_nickname, modifier);

conflict_name = gen_conflict_path (dirname, nickname, (gint64)time(NULL));

out:
g_free (modifier);
return conflict_name;
}

static int
merge_entries (const char *store_id, int version,
int n, SeafDirent *dents[],
const char *basedir,
GList **dents_out,
MergeOptions *opt)
int twoway_merge(const char *store_id, int version, const char *basedir,
SeafDirent *dents[], GList **dents_out, struct MergeOptions *opt)
{
SeafDirent *files[3];
SeafDirent *files[2];
int i;
int n = opt->n_ways;

memset (files, 0, sizeof(files[0])*n);
for (i = 0; i < n; ++i) {
if (dents[i] && S_ISREG(dents[i]->mode))
files[i] = dents[i];
}

/* If we're running 2-way merge, or the caller requires not to
* actually merge contents, just call the callback function.
*/
if (n == 2 || !opt->do_merge)
return opt->callback (basedir, files, opt);
SeafDirent *head, *remote;
char *conflict_name;

/* Otherwise, we're doing a real 3-way merge of the trees.
* It means merge files and handle any conflicts.
*/
head = files[0];
remote = files[1];

if (head && remote) {
if (strcmp (head->id, remote->id) == 0) {
// file match
seaf_debug ("%s%s: files match\n", basedir, head->name);
*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(head));
} else {
// file content conflict
seaf_debug ("%s%s: files conflict\n", basedir, head->name);
conflict_name = merge_conflict_filename(store_id, version,
opt,
basedir,
head->name);
if (!conflict_name)
return -1;

g_free (remote->name);
remote->name = conflict_name;
remote->name_len = strlen (remote->name);

*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(head));
*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(remote));

opt->conflict = TRUE;
}
} else if (!head && remote) {
// file not in head, but in remote
seaf_debug ("%s%s: added in remote\n", basedir, remote->name);
*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(remote));
} else if (head && !remote) {
// file in head, but not in remote
seaf_debug ("%s%s: added in head\n", basedir, head->name);
*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(head));
}

return 0;
}

static int
threeway_merge (const char *store_id, int version,
SeafDirent *dents[],
const char *basedir,
GList **dents_out,
MergeOptions *opt)
{
SeafDirent *files[3];
int i;
gint64 curr_time;
int n = opt->n_ways;

memset (files, 0, sizeof(files[0])*n);
for (i = 0; i < n; ++i) {
if (dents[i] && S_ISREG(dents[i]->mode))
files[i] = dents[i];
}

SeafDirent *base, *head, *remote;
char *conflict_name;
Expand Down Expand Up @@ -323,6 +406,25 @@ merge_entries (const char *store_id, int version,
return 0;
}

static int
merge_entries (const char *store_id, int version,
int n, SeafDirent *dents[],
const char *basedir,
GList **dents_out,
MergeOptions *opt)
{
/* If we're running 2-way merge, it means merge files base on head and remote.
*/
if (n == 2)
return twoway_merge (store_id, version, basedir, dents, dents_out, opt);

/* Otherwise, we're doing a real 3-way merge of the trees.
* It means merge files and handle any conflicts.
*/

return threeway_merge (store_id, version, dents, basedir, dents_out, opt);
}

static int
merge_directories (const char *store_id, int version,
int n, SeafDirent *dents[],
Expand All @@ -345,7 +447,7 @@ merge_directories (const char *store_id, int version,

seaf_debug ("dir_mask = %d\n", dir_mask);

if (n == 3 && opt->do_merge) {
if (n == 3) {
switch (dir_mask) {
case 0:
g_return_val_if_reached (-1);
Expand Down Expand Up @@ -407,6 +509,33 @@ merge_directories (const char *store_id, int version,
default:
g_return_val_if_reached (-1);
}
} else if (n == 2) {
switch (dir_mask) {
case 0:
g_return_val_if_reached (-1);
case 1:
/*head is dir, remote is not dir*/
seaf_debug ("%s%s: only head is dir\n", basedir, dents[0]->name);
*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(dents[0]));
return 0;
case 2:
/*head is not dir, remote is dir*/
seaf_debug ("%s%s: only remote is dir\n", basedir, dents[1]->name);
*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(dents[1]));
return 0;
case 3:
if (strcmp (dents[0]->id, dents[1]->id) == 0) {
seaf_debug ("%s%s: dir is the same in head and remote\n",
basedir, dents[0]->name);
*dents_out = g_list_prepend (*dents_out, seaf_dirent_dup(dents[1]));
return 0;
}
seaf_debug ("%s%s: dir is changed in head and remote, merge recursively\n",
basedir, dents[0]->name);
break;
default:
g_return_val_if_reached (-1);
}
}

memset (sub_dirs, 0, sizeof(sub_dirs[0])*n);
Expand All @@ -433,7 +562,7 @@ merge_directories (const char *store_id, int version,

g_free (new_basedir);

if (n == 3 && opt->do_merge) {
if (n == 3) {
if (dir_mask == 3 || dir_mask == 6 || dir_mask == 7) {
merged_dent = seaf_dirent_dup (dents[1]);
memcpy (merged_dent->id, opt->merged_tree_root, 40);
Expand All @@ -443,6 +572,12 @@ merge_directories (const char *store_id, int version,
memcpy (merged_dent->id, opt->merged_tree_root, 40);
*dents_out = g_list_prepend (*dents_out, merged_dent);
}
} else if (n == 2) {
if (dir_mask == 3) {
merged_dent = seaf_dirent_dup (dents[1]);
memcpy (merged_dent->id, opt->merged_tree_root, 40);
*dents_out = g_list_prepend (*dents_out, merged_dent);
}
}

free_sub_dirs:
Expand Down Expand Up @@ -539,7 +674,7 @@ merge_trees_recursive (const char *store_id, int version,
}
}

if (n == 3 && opt->do_merge) {
if (n == 3) {
merged_dents = g_list_sort (merged_dents, compare_dirents);
merged_tree = seaf_dir_new (NULL, merged_dents,
dir_version_from_repo_version(version));
Expand All @@ -556,6 +691,23 @@ merge_trees_recursive (const char *store_id, int version,
seaf_warning ("Failed to save merged tree %s:%s.\n", store_id, basedir);
}
}
} else if (n == 2) {
merged_dents = g_list_sort (merged_dents, compare_dirents);
merged_tree = seaf_dir_new (NULL, merged_dents,
dir_version_from_repo_version(version));

memcpy (opt->merged_tree_root, merged_tree->dir_id, 40);

if ((trees[0] && strcmp (trees[0]->dir_id, merged_tree->dir_id) == 0) ||
(trees[1] && strcmp (trees[1]->dir_id, merged_tree->dir_id) == 0)) {
seaf_dir_free (merged_tree);
} else {
ret = seaf_dir_save (seaf->fs_mgr, store_id, version, merged_tree);
seaf_dir_free (merged_tree);
if (ret < 0) {
seaf_warning ("Failed to save merged tree %s:%s.\n", store_id, basedir);
}
}
}

return ret;
Expand All @@ -570,6 +722,11 @@ seaf_merge_trees (const char *store_id, int version,

g_return_val_if_fail (n == 2 || n == 3, -1);

opt->email_to_nickname = g_hash_table_new_full(g_str_hash,
g_str_equal,
g_free,
g_free);

trees = g_new0 (SeafDir *, n);
for (i = 0; i < n; ++i) {
root = seaf_fs_manager_get_seafdir (seaf->fs_mgr, store_id, version, roots[i]);
Expand All @@ -587,5 +744,7 @@ seaf_merge_trees (const char *store_id, int version,
seaf_dir_free (trees[i]);
g_free (trees);

g_hash_table_destroy (opt->email_to_nickname);

return ret;
}
2 changes: 2 additions & 0 deletions common/merge-new.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ typedef struct MergeOptions {
char merged_tree_root[41]; /* merge result */
int visit_dirs;
gboolean conflict;

GHashTable *email_to_nickname;
} MergeOptions;

int
Expand Down
Loading

0 comments on commit 11d4741

Please sign in to comment.