@@ -38,6 +38,7 @@ PG_FUNCTION_INFO_V1(git_fdw_validator);
3838
3939#define POSTGRES_TO_UNIX_EPOCH_DAYS (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE)
4040#define POSTGRES_TO_UNIX_EPOCH_USECS (POSTGRES_TO_UNIX_EPOCH_DAYS * USECS_PER_DAY)
41+ #define DEFAULT_BRANCH "master"
4142
4243static void gitGetForeignRelSize (PlannerInfo * root , RelOptInfo * baserel , Oid foreigntableid );
4344static void gitGetForeignPaths (PlannerInfo * root , RelOptInfo * baserel , Oid foreigntableid );
@@ -50,7 +51,7 @@ static void fileReScanForeignScan(ForeignScanState *node);
5051static void gitEndForeignScan (ForeignScanState * node );
5152
5253static bool is_valid_option (const char * option , Oid context );
53- static void gitGetOptions (Oid foreigntableid , char * * path , List * * other_options );
54+ static void gitGetOptions (Oid foreigntableid , GitFdwPlanState * state , List * * other_options );
5455static void estimate_costs (PlannerInfo * root , RelOptInfo * baserel ,
5556 GitFdwPlanState * fdw_private ,
5657 Cost * startup_cost , Cost * total_cost );
@@ -75,7 +76,8 @@ Datum git_fdw_handler(PG_FUNCTION_ARGS) {
7576Datum git_fdw_validator (PG_FUNCTION_ARGS ) {
7677 List * options_list = untransformRelOptions (PG_GETARG_DATUM (0 ));
7778 Oid catalog = PG_GETARG_OID (1 );
78- char * path = NULL ;
79+ char * path = NULL ;
80+ char * branch = NULL ;
7981 List * other_options = NIL ;
8082 ListCell * cell ;
8183
@@ -116,6 +118,14 @@ Datum git_fdw_validator(PG_FUNCTION_ARGS) {
116118 errmsg ("conflicting or redundant options" )));
117119 path = defGetString (def );
118120 }
121+ else if (strcmp (def -> defname , "branch" ) == 0 )
122+ {
123+ if (branch )
124+ ereport (ERROR ,
125+ (errcode (ERRCODE_SYNTAX_ERROR ),
126+ errmsg ("conflicting or redundant options" )));
127+ branch = defGetString (def );
128+ }
119129 else
120130 other_options = lappend (other_options , def );
121131 }
@@ -130,6 +140,7 @@ Datum git_fdw_validator(PG_FUNCTION_ARGS) {
130140// FIXME: Avoid global variable
131141// TODO: Find where this variable should go (Plan or Path?)
132142char * repository_path ;
143+ char * repository_branch ;
133144
134145static bool is_valid_option (const char * option , Oid context ) {
135146 const struct GitFdwOption * opt ;
@@ -142,7 +153,7 @@ static bool is_valid_option(const char *option, Oid context) {
142153}
143154
144155// Fetch path and options from the server (only)
145- static void gitGetOptions (Oid foreigntableid , char * * path , List * * other_options ) {
156+ static void gitGetOptions (Oid foreigntableid , GitFdwPlanState * state , List * * other_options ) {
146157 ForeignTable * table ;
147158 List * options ;
148159 ListCell * lc ,
@@ -153,24 +164,31 @@ static void gitGetOptions(Oid foreigntableid, char **path, List **other_options)
153164 options = NIL ;
154165 options = list_concat (options , table -> options );
155166
156- * path = NULL ;
157-
158167 prev = NULL ;
159168 foreach (lc , options ) {
160169 DefElem * def = (DefElem * ) lfirst (lc );
161170
162171 if (strcmp (def -> defname , "path" ) == 0 ) {
163- * path = defGetString (def );
172+ state -> path = defGetString (def );
164173 options = list_delete_cell (options , lc , prev );
165- break ;
166174 }
175+
176+ if (strcmp (def -> defname , "branch" ) == 0 ) {
177+ state -> branch = defGetString (def );
178+ options = list_delete_cell (options , lc , prev );
179+ }
180+
167181 prev = lc ;
168182 }
169183
170- if (* path == NULL ) {
184+ if (state -> path == NULL ) {
171185 elog (ERROR , "path is required for git_fdw foreign tables (path of the .git repo)" );
172186 }
173187
188+ if (state -> branch == NULL ) {
189+ state -> branch = DEFAULT_BRANCH ;
190+ }
191+
174192 * other_options = options ;
175193}
176194
@@ -180,7 +198,7 @@ static void gitGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid for
180198 // Pass path and options from the options (only the table for now, but
181199 // could be from the server too) into the baserel
182200 fdw_private = (GitFdwPlanState * ) palloc (sizeof (GitFdwPlanState ));
183- gitGetOptions (foreigntableid , & fdw_private -> path , & fdw_private -> options );
201+ gitGetOptions (foreigntableid , fdw_private , & fdw_private -> options );
184202 baserel -> fdw_private = (void * ) fdw_private ;
185203 // TODO: We should estimate baserel->rows
186204}
@@ -219,7 +237,8 @@ static ForeignScan * gitGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, O
219237 ForeignScan * scan = make_foreignscan (tlist , scan_clauses , scan_relid , NIL , best_path -> fdw_private );
220238
221239 //ForeignScan * scan = make_foreignscan(tlist, scan_clauses, scan_relid, NIL, baserel->fdw_private);
222- repository_path = ((GitFdwPlanState * )scan -> fdw_private )-> path ;
240+ repository_path = ((GitFdwPlanState * )scan -> fdw_private )-> path ;
241+ repository_branch = ((GitFdwPlanState * )scan -> fdw_private )-> branch ;
223242 return scan ;
224243}
225244
@@ -233,8 +252,9 @@ static void gitBeginForeignScan(ForeignScanState *node, int eflags) {
233252 git_oid oid ;
234253
235254 festate = (GitFdwExecutionState * ) palloc (sizeof (GitFdwExecutionState ));
236- festate -> path = repository_path ;
237- festate -> repo = NULL ;
255+ festate -> path = repository_path ;
256+ festate -> branch = repository_branch ;
257+ festate -> repo = NULL ;
238258 festate -> walker = NULL ;
239259
240260 node -> fdw_state = (void * ) festate ;
@@ -246,18 +266,17 @@ static void gitBeginForeignScan(ForeignScanState *node, int eflags) {
246266 return ;
247267 }
248268
249- // Read HEAD on master
269+ // Read HEAD on specified branch (DEFAULT_BRANCH by default)
250270 char head_filepath [512 ];
251271 FILE * head_fileptr ;
252272 char head_rev [41 ];
253273
254274 strcpy (head_filepath , festate -> path );
255-
256275 if (strrchr (festate -> path , '/' ) != (festate -> path + strlen (festate -> path )))
257- strcat (head_filepath , "/refs/heads/master " );
276+ strcat (head_filepath , "/refs/heads/" );
258277 else
259- strcat (head_filepath , "refs/heads/master " );
260-
278+ strcat (head_filepath , "refs/heads/" );
279+ strcat ( head_filepath , festate -> branch );
261280
262281 if ((head_fileptr = fopen (head_filepath , "r" )) == NULL ){
263282 elog (ERROR , "Error opening '%s'\n" , head_filepath );
0 commit comments