1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) James Liggett 2008 <jrliggett@cox.net>
6 * anjuta is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
13 * anjuta is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with anjuta. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
25 #include "git-ref-command.h"
27 #define BRANCH_REF_REGEX "([[:xdigit:]]{40}) refs/heads/(.*)"
28 #define TAG_REF_REGEX "([[:xdigit:]]{40}) refs/tags/(.*)"
29 #define REMOTE_REF_REGEX "([[:xdigit:]]{40}) refs/remotes/(.*)"
31 struct _GitRefCommandPriv
33 GRegex
*branch_ref_regex
;
34 GRegex
*tag_ref_regex
;
35 GRegex
*remote_ref_regex
;
39 G_DEFINE_TYPE (GitRefCommand
, git_ref_command
, GIT_TYPE_COMMAND
);
42 free_refs_list (GList
*refs
)
50 g_object_unref (current_ref
->data
);
51 current_ref
= g_list_next (current_ref
);
58 git_ref_command_init (GitRefCommand
*self
)
60 self
->priv
= g_new0 (GitRefCommandPriv
, 1);
62 self
->priv
->branch_ref_regex
= g_regex_new (BRANCH_REF_REGEX
, 0, 0, NULL
);
63 self
->priv
->tag_ref_regex
= g_regex_new (TAG_REF_REGEX
, 0, 0, NULL
);
64 self
->priv
->remote_ref_regex
= g_regex_new (REMOTE_REF_REGEX
, 0, 0, NULL
);
65 self
->priv
->refs
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
67 (GDestroyNotify
) free_refs_list
);
71 git_ref_command_finalize (GObject
*object
)
75 self
= GIT_REF_COMMAND (object
);
77 g_regex_unref (self
->priv
->branch_ref_regex
);
78 g_regex_unref (self
->priv
->tag_ref_regex
);
79 g_regex_unref (self
->priv
->remote_ref_regex
);
80 g_hash_table_unref (self
->priv
->refs
);
84 G_OBJECT_CLASS (git_ref_command_parent_class
)->finalize (object
);
88 git_ref_command_run (AnjutaCommand
*command
)
90 git_command_add_arg (GIT_COMMAND (command
), "show-ref");
91 git_command_add_arg (GIT_COMMAND (command
), "--dereference");
97 git_ref_command_insert_ref (GitRefCommand
*self
, const gchar
*sha
, GitRef
*ref
)
103 name
= git_ref_get_name (ref
);
105 ref_list
= g_hash_table_lookup (self
->priv
->refs
, sha
);
107 ref_list
= g_list_append (ref_list
, ref
);
109 if (g_hash_table_lookup_extended (self
->priv
->refs
, sha
,
110 (gpointer
) &old_sha
, NULL
))
112 /* Change the list head for this SHA without destroying it */
113 g_hash_table_steal (self
->priv
->refs
, sha
);
118 g_hash_table_insert (self
->priv
->refs
, g_strdup (sha
), ref_list
);
124 git_ref_command_handle_output (GitCommand
*git_command
, const gchar
*output
)
127 GMatchInfo
*match_info
;
132 self
= GIT_REF_COMMAND (git_command
);
135 if (g_regex_match (self
->priv
->branch_ref_regex
, output
, 0, &match_info
))
137 sha
= g_match_info_fetch (match_info
, 1);
138 name
= g_match_info_fetch (match_info
, 2);
139 ref
= git_ref_new (name
, GIT_REF_TYPE_BRANCH
);
141 git_ref_command_insert_ref (self
, sha
, ref
);
146 else if (g_regex_match (self
->priv
->tag_ref_regex
, output
, 0, &match_info
))
148 sha
= g_match_info_fetch (match_info
, 1);
149 name
= g_match_info_fetch (match_info
, 2);
151 if (g_str_has_suffix (name
, "^{}"))
152 (g_strrstr (name
, "^{}")) [0] = '\0';
154 ref
= git_ref_new (name
, GIT_REF_TYPE_TAG
);
157 git_ref_command_insert_ref (self
, sha
, ref
);
162 else if (g_regex_match (self
->priv
->remote_ref_regex
, output
, 0,
165 sha
= g_match_info_fetch (match_info
, 1);
166 name
= g_match_info_fetch (match_info
, 2);
167 ref
= git_ref_new (name
, GIT_REF_TYPE_REMOTE
);
169 git_ref_command_insert_ref (self
, sha
, ref
);
176 g_match_info_free (match_info
);
180 git_ref_command_class_init (GitRefCommandClass
*klass
)
182 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
183 GitCommandClass
* parent_class
= GIT_COMMAND_CLASS (klass
);
184 AnjutaCommandClass
*command_class
= ANJUTA_COMMAND_CLASS (klass
);
186 object_class
->finalize
= git_ref_command_finalize
;
187 parent_class
->output_handler
= git_ref_command_handle_output
;
188 command_class
->run
= git_ref_command_run
;
193 git_ref_command_new (const gchar
*working_directory
)
195 return g_object_new (GIT_TYPE_REF_COMMAND
,
196 "working-directory", working_directory
,
197 "single-line-output", TRUE
,
202 git_ref_command_get_refs (GitRefCommand
*self
)
204 return g_hash_table_ref (self
->priv
->refs
);