2005-11-03 03:19:24 +08:00
# include "cache.h"
# include "commit.h"
# include "tag.h"
# include "blob.h"
2005-11-19 03:02:58 +08:00
# include "http.h"
2006-03-08 08:13:20 +08:00
# include "refs.h"
2006-04-11 09:14:54 +08:00
# include "diff.h"
2006-03-08 08:13:20 +08:00
# include "revision.h"
2006-03-21 02:31:06 +08:00
# include "exec_cmd.h"
2007-05-12 23:45:59 +08:00
# include "remote.h"
2008-06-08 02:39:20 +08:00
# include "list-objects.h"
chain kill signals for cleanup functions
If a piece of code wanted to do some cleanup before exiting
(e.g., cleaning up a lockfile or a tempfile), our usual
strategy was to install a signal handler that did something
like this:
do_cleanup(); /* actual work */
signal(signo, SIG_DFL); /* restore previous behavior */
raise(signo); /* deliver signal, killing ourselves */
For a single handler, this works fine. However, if we want
to clean up two _different_ things, we run into a problem.
The most recently installed handler will run, but when it
removes itself as a handler, it doesn't put back the first
handler.
This patch introduces sigchain, a tiny library for handling
a stack of signal handlers. You sigchain_push each handler,
and use sigchain_pop to restore whoever was before you in
the stack.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-22 14:02:35 +08:00
# include "sigchain.h"
2005-11-19 03:02:58 +08:00
2013-02-12 06:03:45 +08:00
# ifdef EXPAT_NEEDS_XMLPARSE_H
# include <xmlparse.h>
# else
2005-11-07 05:07:45 +08:00
# include <expat.h>
2013-02-12 06:03:45 +08:00
# endif
2005-11-03 03:19:24 +08:00
static const char http_push_usage [ ] =
2008-07-13 21:36:15 +08:00
" git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...] \n " ;
2005-11-03 03:19:24 +08:00
2005-11-08 02:23:11 +08:00
# ifndef XML_STATUS_OK
enum XML_Status {
XML_STATUS_OK = 1 ,
XML_STATUS_ERROR = 0
} ;
# define XML_STATUS_OK 1
# define XML_STATUS_ERROR 0
# endif
2006-03-11 12:18:18 +08:00
# define PREV_BUF_SIZE 4096
2005-11-03 03:19:24 +08:00
2005-11-19 03:03:18 +08:00
/* DAV methods */
2005-11-03 03:19:24 +08:00
# define DAV_LOCK "LOCK"
# define DAV_MKCOL "MKCOL"
# define DAV_MOVE "MOVE"
# define DAV_PROPFIND "PROPFIND"
# define DAV_PUT "PUT"
# define DAV_UNLOCK "UNLOCK"
2006-03-21 02:31:06 +08:00
# define DAV_DELETE "DELETE"
2005-11-19 03:03:18 +08:00
/* DAV lock flags */
# define DAV_PROP_LOCKWR (1u << 0)
# define DAV_PROP_LOCKEX (1u << 1)
# define DAV_LOCK_OK (1u << 2)
/* DAV XML properties */
# define DAV_CTX_LOCKENTRY ".multistatus.response.propstat.prop.supportedlock.lockentry"
# define DAV_CTX_LOCKTYPE_WRITE ".multistatus.response.propstat.prop.supportedlock.lockentry.locktype.write"
# define DAV_CTX_LOCKTYPE_EXCLUSIVE ".multistatus.response.propstat.prop.supportedlock.lockentry.lockscope.exclusive"
# define DAV_ACTIVELOCK_OWNER ".prop.lockdiscovery.activelock.owner.href"
# define DAV_ACTIVELOCK_TIMEOUT ".prop.lockdiscovery.activelock.timeout"
# define DAV_ACTIVELOCK_TOKEN ".prop.lockdiscovery.activelock.locktoken.href"
2006-03-08 08:13:20 +08:00
# define DAV_PROPFIND_RESP ".multistatus.response"
# define DAV_PROPFIND_NAME ".multistatus.response.href"
# define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection"
2005-11-19 03:03:18 +08:00
/* DAV request body templates */
2006-03-08 08:13:20 +08:00
# define PROPFIND_SUPPORTEDLOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"%s\">\n<D:supportedlock / >\n< / D:prop>\n< / D:propfind>"
# define PROPFIND_ALL_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop / >\n< / D:propfind>"
2005-11-03 03:19:24 +08:00
# define LOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:lockinfo xmlns:D=\"DAV:\">\n<D:lockscope><D:exclusive / >< / D:lockscope>\n<D:locktype><D:write / >< / D:locktype>\n<D:owner>\n<D:href>mailto:%s< / D:href>\n< / D:owner>\n< / D:lockinfo>"
2005-11-05 06:22:35 +08:00
# define LOCK_TIME 600
# define LOCK_REFRESH 30
2006-04-17 09:12:49 +08:00
/* bits #0-15 in revision.h */
2006-03-08 08:13:20 +08:00
2006-04-17 09:12:49 +08:00
# define LOCAL (1u<<16)
# define REMOTE (1u<<17)
# define FETCHING (1u<<18)
# define PUSHING (1u<<19)
2006-03-08 08:13:20 +08:00
2006-03-21 02:31:06 +08:00
/* We allow "recursive" symbolic refs. Only within reason, though */
# define MAXDEPTH 5
2006-08-16 01:23:48 +08:00
static int pushing ;
static int aborted ;
2006-03-21 03:50:51 +08:00
static signed char remote_dir_exists [ 256 ] ;
2005-11-03 03:19:24 +08:00
2006-08-16 01:23:48 +08:00
static int push_verbosely ;
2007-11-10 07:32:10 +08:00
static int push_all = MATCH_REFS_NONE ;
2006-08-16 01:23:48 +08:00
static int force_all ;
2007-10-16 12:35:22 +08:00
static int dry_run ;
2009-10-31 08:47:30 +08:00
static int helper_status ;
2005-11-03 03:19:24 +08:00
2006-08-16 01:23:48 +08:00
static struct object_list * objects ;
2006-03-08 08:13:20 +08:00
2011-03-16 15:08:34 +08:00
struct repo {
2005-11-03 03:19:24 +08:00
char * url ;
2008-12-23 16:31:15 +08:00
char * path ;
2006-03-08 08:13:20 +08:00
int path_len ;
2006-03-11 12:18:18 +08:00
int has_info_refs ;
int can_update_info_refs ;
int has_info_packs ;
2005-11-03 03:19:24 +08:00
struct packed_git * packs ;
2006-03-11 12:18:12 +08:00
struct remote_lock * locks ;
2005-11-03 03:19:24 +08:00
} ;
2009-03-19 07:43:53 +08:00
static struct repo * repo ;
2005-11-03 03:19:24 +08:00
enum transfer_state {
2006-03-11 12:18:18 +08:00
NEED_FETCH ,
RUN_FETCH_LOOSE ,
RUN_FETCH_PACKED ,
2005-11-03 03:19:24 +08:00
NEED_PUSH ,
RUN_MKCOL ,
RUN_PUT ,
RUN_MOVE ,
ABORTED ,
2010-05-14 17:31:35 +08:00
COMPLETE
2005-11-03 03:19:24 +08:00
} ;
2011-03-16 15:08:34 +08:00
struct transfer_request {
2006-03-08 08:13:20 +08:00
struct object * obj ;
2005-11-03 03:19:24 +08:00
char * url ;
char * dest ;
2006-03-08 08:13:20 +08:00
struct remote_lock * lock ;
2005-11-03 03:19:24 +08:00
struct curl_slist * headers ;
struct buffer buffer ;
enum transfer_state state ;
CURLcode curl_result ;
char errorstr [ CURL_ERROR_SIZE ] ;
long http_code ;
2006-03-11 12:18:18 +08:00
void * userData ;
2005-11-03 03:19:24 +08:00
struct active_request_slot * slot ;
struct transfer_request * next ;
} ;
2006-08-16 01:23:48 +08:00
static struct transfer_request * request_queue_head ;
2005-11-03 03:19:24 +08:00
2011-03-16 15:08:34 +08:00
struct xml_ctx {
2005-11-19 03:03:18 +08:00
char * name ;
int len ;
char * cdata ;
void ( * userFunc ) ( struct xml_ctx * ctx , int tag_closed ) ;
void * userData ;
} ;
2011-03-16 15:08:34 +08:00
struct remote_lock {
2005-11-05 06:22:35 +08:00
char * url ;
2005-11-05 06:22:31 +08:00
char * owner ;
2005-11-05 06:22:35 +08:00
char * token ;
use a hash of the lock token as the suffix for PUT/MOVE
After 753bc91 ("Remove the requirement opaquelocktoken uri scheme"),
lock tokens are in the URI forms in which they are received from the
server, eg. 'opaquelocktoken:', 'urn:uuid:'.
However, "start_put" (and consequently "start_move"), which attempts to
create a unique temporary file using the UUID of the lock token,
inadvertently uses the lock token in its URI form. These file
operations on the server may not be successful (specifically, in
Windows), due to the colon ':' character from the URI form of the lock
token in the file path.
This patch uses a hash of the lock token instead, guaranteeing only
"safe" characters (a-f, 0-9) are used in the file path.
The token's hash is generated when the lock token is received from the
server in handle_new_lock_ctx, minimizing the number of times of
hashing.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-02-14 17:52:14 +08:00
char tmpfile_suffix [ 41 ] ;
2005-11-05 06:22:31 +08:00
time_t start_time ;
long timeout ;
2005-11-05 06:22:35 +08:00
int refreshing ;
2006-03-08 08:13:20 +08:00
struct remote_lock * next ;
} ;
2006-03-11 12:18:08 +08:00
/* Flags that control remote_ls processing */
# define PROCESS_FILES (1u << 0)
# define PROCESS_DIRS (1u << 1)
# define RECURSIVE (1u << 2)
/* Flags that remote_ls passes to callback functions */
# define IS_DIR (1u << 0)
2011-03-16 15:08:34 +08:00
struct remote_ls_ctx {
2006-03-11 12:18:08 +08:00
char * path ;
void ( * userFunc ) ( struct remote_ls_ctx * ls ) ;
void * userData ;
int flags ;
char * dentry_name ;
int dentry_flags ;
struct remote_ls_ctx * parent ;
2005-11-05 06:22:31 +08:00
} ;
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
/* get_dav_token_headers options */
enum dav_header_flag {
DAV_HEADER_IF = ( 1u < < 0 ) ,
DAV_HEADER_LOCK = ( 1u < < 1 ) ,
DAV_HEADER_TIMEOUT = ( 1u < < 2 )
} ;
2011-05-03 23:47:28 +08:00
static char * xml_entities ( const char * s )
2009-04-10 06:25:37 +08:00
{
struct strbuf buf = STRBUF_INIT ;
2012-11-25 19:08:35 +08:00
strbuf_addstr_xml_quoted ( & buf , s ) ;
2009-04-10 06:25:37 +08:00
return strbuf_detach ( & buf , NULL ) ;
}
2011-05-03 23:47:29 +08:00
static void curl_setup_http_get ( CURL * curl , const char * url ,
const char * custom_req )
{
curl_easy_setopt ( curl , CURLOPT_HTTPGET , 1 ) ;
curl_easy_setopt ( curl , CURLOPT_URL , url ) ;
curl_easy_setopt ( curl , CURLOPT_CUSTOMREQUEST , custom_req ) ;
curl_easy_setopt ( curl , CURLOPT_WRITEFUNCTION , fwrite_null ) ;
}
static void curl_setup_http ( CURL * curl , const char * url ,
const char * custom_req , struct buffer * buffer ,
curl_write_callback write_fn )
{
curl_easy_setopt ( curl , CURLOPT_PUT , 1 ) ;
curl_easy_setopt ( curl , CURLOPT_URL , url ) ;
curl_easy_setopt ( curl , CURLOPT_INFILE , buffer ) ;
curl_easy_setopt ( curl , CURLOPT_INFILESIZE , buffer - > buf . len ) ;
curl_easy_setopt ( curl , CURLOPT_READFUNCTION , fread_buffer ) ;
# ifndef NO_CURL_IOCTL
curl_easy_setopt ( curl , CURLOPT_IOCTLFUNCTION , ioctl_buffer ) ;
curl_easy_setopt ( curl , CURLOPT_IOCTLDATA , & buffer ) ;
# endif
curl_easy_setopt ( curl , CURLOPT_WRITEFUNCTION , write_fn ) ;
curl_easy_setopt ( curl , CURLOPT_NOBODY , 0 ) ;
curl_easy_setopt ( curl , CURLOPT_CUSTOMREQUEST , custom_req ) ;
curl_easy_setopt ( curl , CURLOPT_UPLOAD , 1 ) ;
}
2009-01-25 16:04:15 +08:00
static struct curl_slist * get_dav_token_headers ( struct remote_lock * lock , enum dav_header_flag options )
{
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
struct strbuf buf = STRBUF_INIT ;
struct curl_slist * dav_headers = NULL ;
2009-01-25 16:04:15 +08:00
if ( options & DAV_HEADER_IF ) {
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
strbuf_addf ( & buf , " If: (<%s>) " , lock - > token ) ;
dav_headers = curl_slist_append ( dav_headers , buf . buf ) ;
strbuf_reset ( & buf ) ;
}
2009-01-25 16:04:15 +08:00
if ( options & DAV_HEADER_LOCK ) {
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
strbuf_addf ( & buf , " Lock-Token: <%s> " , lock - > token ) ;
dav_headers = curl_slist_append ( dav_headers , buf . buf ) ;
strbuf_reset ( & buf ) ;
}
2009-01-25 16:04:15 +08:00
if ( options & DAV_HEADER_TIMEOUT ) {
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
strbuf_addf ( & buf , " Timeout: Second-%ld " , lock - > timeout ) ;
dav_headers = curl_slist_append ( dav_headers , buf . buf ) ;
strbuf_reset ( & buf ) ;
}
strbuf_release ( & buf ) ;
return dav_headers ;
}
2005-11-19 03:02:58 +08:00
static void finish_request ( struct transfer_request * request ) ;
2006-03-11 12:18:18 +08:00
static void release_request ( struct transfer_request * request ) ;
2005-11-03 03:19:24 +08:00
2005-11-19 03:02:58 +08:00
static void process_response ( void * callback_data )
2005-11-03 03:19:24 +08:00
{
2005-11-19 03:02:58 +08:00
struct transfer_request * request =
( struct transfer_request * ) callback_data ;
2005-11-03 03:19:24 +08:00
2005-11-19 03:02:58 +08:00
finish_request ( request ) ;
2005-11-03 03:19:24 +08:00
}
2006-06-07 05:26:57 +08:00
# ifdef USE_CURL_MULTI
2009-02-03 14:24:40 +08:00
2006-03-11 12:18:18 +08:00
static void start_fetch_loose ( struct transfer_request * request )
{
struct active_request_slot * slot ;
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
struct http_object_request * obj_req ;
2006-03-11 12:18:18 +08:00
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
obj_req = new_http_object_request ( repo - > url , request - > obj - > sha1 ) ;
if ( obj_req = = NULL ) {
2006-03-11 12:18:18 +08:00
request - > state = ABORTED ;
return ;
}
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
slot = obj_req - > slot ;
2006-03-11 12:18:18 +08:00
slot - > callback_func = process_response ;
slot - > callback_data = request ;
request - > slot = slot ;
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
request - > userData = obj_req ;
2006-03-11 12:18:18 +08:00
/* Try to get the request started, abort the request on error */
request - > state = RUN_FETCH_LOOSE ;
if ( ! start_active_slot ( slot ) ) {
fprintf ( stderr , " Unable to start GET request \n " ) ;
2009-03-19 07:43:53 +08:00
repo - > can_update_info_refs = 0 ;
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
release_http_object_request ( obj_req ) ;
2006-03-11 12:18:18 +08:00
release_request ( request ) ;
}
}
2006-06-07 05:26:57 +08:00
static void start_mkcol ( struct transfer_request * request )
{
char * hex = sha1_to_hex ( request - > obj - > sha1 ) ;
struct active_request_slot * slot ;
2009-03-19 07:43:53 +08:00
request - > url = get_remote_object_url ( repo - > url , hex , 1 ) ;
2006-06-07 05:26:57 +08:00
slot = get_active_slot ( ) ;
slot - > callback_func = process_response ;
slot - > callback_data = request ;
2011-05-03 23:47:29 +08:00
curl_setup_http_get ( slot - > curl , request - > url , DAV_MKCOL ) ;
2006-06-07 05:26:57 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_ERRORBUFFER , request - > errorstr ) ;
if ( start_active_slot ( slot ) ) {
request - > slot = slot ;
request - > state = RUN_MKCOL ;
} else {
request - > state = ABORTED ;
free ( request - > url ) ;
request - > url = NULL ;
}
}
# endif
2006-03-11 12:18:18 +08:00
static void start_fetch_packed ( struct transfer_request * request )
{
struct packed_git * target ;
struct transfer_request * check_request = request_queue_head ;
2009-06-06 16:44:01 +08:00
struct http_pack_request * preq ;
2006-03-11 12:18:18 +08:00
2009-03-19 07:43:53 +08:00
target = find_sha1_pack ( request - > obj - > sha1 , repo - > packs ) ;
2006-03-11 12:18:18 +08:00
if ( ! target ) {
fprintf ( stderr , " Unable to fetch %s, will not be able to update server info refs \n " , sha1_to_hex ( request - > obj - > sha1 ) ) ;
2009-03-19 07:43:53 +08:00
repo - > can_update_info_refs = 0 ;
2006-03-11 12:18:18 +08:00
release_request ( request ) ;
return ;
}
fprintf ( stderr , " Fetching pack %s \n " , sha1_to_hex ( target - > sha1 ) ) ;
fprintf ( stderr , " which contains %s \n " , sha1_to_hex ( request - > obj - > sha1 ) ) ;
2009-06-06 16:44:01 +08:00
preq = new_http_pack_request ( target , repo - > url ) ;
if ( preq = = NULL ) {
release_http_pack_request ( preq ) ;
repo - > can_update_info_refs = 0 ;
return ;
}
preq - > lst = & repo - > packs ;
2006-03-11 12:18:18 +08:00
/* Make sure there isn't another open request for this pack */
while ( check_request ) {
if ( check_request - > state = = RUN_FETCH_PACKED & &
2009-06-06 16:44:01 +08:00
! strcmp ( check_request - > url , preq - > url ) ) {
release_http_pack_request ( preq ) ;
2006-03-11 12:18:18 +08:00
release_request ( request ) ;
return ;
}
check_request = check_request - > next ;
}
2009-06-06 16:44:01 +08:00
preq - > slot - > callback_func = process_response ;
preq - > slot - > callback_data = request ;
request - > slot = preq - > slot ;
request - > userData = preq ;
2006-03-11 12:18:18 +08:00
/* Try to get the request started, abort the request on error */
request - > state = RUN_FETCH_PACKED ;
2009-06-06 16:44:01 +08:00
if ( ! start_active_slot ( preq - > slot ) ) {
2006-03-11 12:18:18 +08:00
fprintf ( stderr , " Unable to start GET request \n " ) ;
2009-06-06 16:44:01 +08:00
release_http_pack_request ( preq ) ;
2009-03-19 07:43:53 +08:00
repo - > can_update_info_refs = 0 ;
2006-03-11 12:18:18 +08:00
release_request ( request ) ;
}
}
2005-11-03 03:19:24 +08:00
static void start_put ( struct transfer_request * request )
{
2006-03-08 08:13:20 +08:00
char * hex = sha1_to_hex ( request - > obj - > sha1 ) ;
2005-11-03 03:19:24 +08:00
struct active_request_slot * slot ;
2009-01-31 07:51:55 +08:00
struct strbuf buf = STRBUF_INIT ;
2007-02-27 03:55:59 +08:00
enum object_type type ;
2005-11-03 03:19:24 +08:00
char hdr [ 50 ] ;
void * unpacked ;
unsigned long len ;
int hdrlen ;
ssize_t size ;
2011-06-11 02:52:15 +08:00
git_zstream stream ;
2005-11-03 03:19:24 +08:00
2007-02-27 03:55:59 +08:00
unpacked = read_sha1_file ( request - > obj - > sha1 , & type , & len ) ;
hdrlen = sprintf ( hdr , " %s %lu " , typename ( type ) , len ) + 1 ;
2005-11-03 03:19:24 +08:00
/* Set it up */
memset ( & stream , 0 , sizeof ( stream ) ) ;
2011-06-11 01:55:10 +08:00
git_deflate_init ( & stream , zlib_compression_level ) ;
2011-06-11 02:18:17 +08:00
size = git_deflate_bound ( & stream , len + hdrlen ) ;
2007-12-10 03:30:59 +08:00
strbuf_init ( & request - > buffer . buf , size ) ;
request - > buffer . posn = 0 ;
2005-11-03 03:19:24 +08:00
/* Compress it */
2007-12-10 03:30:59 +08:00
stream . next_out = ( unsigned char * ) request - > buffer . buf . buf ;
2005-11-03 03:19:24 +08:00
stream . avail_out = size ;
/* First header.. */
stream . next_in = ( void * ) hdr ;
stream . avail_in = hdrlen ;
2011-06-11 01:55:10 +08:00
while ( git_deflate ( & stream , 0 ) = = Z_OK )
; /* nothing */
2005-11-03 03:19:24 +08:00
/* Then the data itself.. */
stream . next_in = unpacked ;
stream . avail_in = len ;
2011-06-11 01:55:10 +08:00
while ( git_deflate ( & stream , Z_FINISH ) = = Z_OK )
; /* nothing */
git_deflate_end ( & stream ) ;
2005-11-03 03:19:24 +08:00
free ( unpacked ) ;
2007-12-10 03:30:59 +08:00
request - > buffer . buf . len = stream . total_out ;
2005-11-03 03:19:24 +08:00
2009-01-31 07:51:55 +08:00
strbuf_addstr ( & buf , " Destination: " ) ;
2009-03-19 07:43:53 +08:00
append_remote_object_url ( & buf , repo - > url , hex , 0 ) ;
2009-01-31 07:51:55 +08:00
request - > dest = strbuf_detach ( & buf , NULL ) ;
2009-03-19 07:43:53 +08:00
append_remote_object_url ( & buf , repo - > url , hex , 0 ) ;
use a hash of the lock token as the suffix for PUT/MOVE
After 753bc91 ("Remove the requirement opaquelocktoken uri scheme"),
lock tokens are in the URI forms in which they are received from the
server, eg. 'opaquelocktoken:', 'urn:uuid:'.
However, "start_put" (and consequently "start_move"), which attempts to
create a unique temporary file using the UUID of the lock token,
inadvertently uses the lock token in its URI form. These file
operations on the server may not be successful (specifically, in
Windows), due to the colon ':' character from the URI form of the lock
token in the file path.
This patch uses a hash of the lock token instead, guaranteeing only
"safe" characters (a-f, 0-9) are used in the file path.
The token's hash is generated when the lock token is received from the
server in handle_new_lock_ctx, minimizing the number of times of
hashing.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-02-14 17:52:14 +08:00
strbuf_add ( & buf , request - > lock - > tmpfile_suffix , 41 ) ;
2009-01-31 07:51:55 +08:00
request - > url = strbuf_detach ( & buf , NULL ) ;
2005-11-03 03:19:24 +08:00
slot = get_active_slot ( ) ;
2005-11-19 03:02:58 +08:00
slot - > callback_func = process_response ;
slot - > callback_data = request ;
2011-05-03 23:47:29 +08:00
curl_setup_http ( slot - > curl , request - > url , DAV_PUT ,
& request - > buffer , fwrite_null ) ;
2005-11-03 03:19:24 +08:00
if ( start_active_slot ( slot ) ) {
request - > slot = slot ;
request - > state = RUN_PUT ;
} else {
request - > state = ABORTED ;
free ( request - > url ) ;
2005-11-19 03:03:25 +08:00
request - > url = NULL ;
2005-11-03 03:19:24 +08:00
}
}
static void start_move ( struct transfer_request * request )
{
struct active_request_slot * slot ;
struct curl_slist * dav_headers = NULL ;
slot = get_active_slot ( ) ;
2005-11-19 03:02:58 +08:00
slot - > callback_func = process_response ;
slot - > callback_data = request ;
2011-05-03 23:47:29 +08:00
curl_setup_http_get ( slot - > curl , request - > url , DAV_MOVE ) ;
2005-11-03 03:19:24 +08:00
dav_headers = curl_slist_append ( dav_headers , request - > dest ) ;
dav_headers = curl_slist_append ( dav_headers , " Overwrite: T " ) ;
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
if ( start_active_slot ( slot ) ) {
request - > slot = slot ;
request - > state = RUN_MOVE ;
} else {
request - > state = ABORTED ;
free ( request - > url ) ;
2005-11-19 03:03:25 +08:00
request - > url = NULL ;
2005-11-03 03:19:24 +08:00
}
}
2006-03-11 12:18:12 +08:00
static int refresh_lock ( struct remote_lock * lock )
2005-11-05 06:22:35 +08:00
{
struct active_request_slot * slot ;
2006-03-11 12:18:01 +08:00
struct slot_results results ;
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
struct curl_slist * dav_headers ;
2006-03-11 12:18:12 +08:00
int rc = 0 ;
2005-11-05 06:22:35 +08:00
2006-03-11 12:18:12 +08:00
lock - > refreshing = 1 ;
2005-11-05 06:22:35 +08:00
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
dav_headers = get_dav_token_headers ( lock , DAV_HEADER_IF | DAV_HEADER_TIMEOUT ) ;
2005-11-05 06:22:35 +08:00
2006-03-11 12:18:12 +08:00
slot = get_active_slot ( ) ;
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http_get ( slot - > curl , lock - > url , DAV_LOCK ) ;
2006-03-11 12:18:12 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
2005-11-05 06:22:35 +08:00
2006-03-11 12:18:12 +08:00
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
if ( results . curl_result ! = CURLE_OK ) {
fprintf ( stderr , " LOCK HTTP error %ld \n " ,
results . http_code ) ;
} else {
lock - > start_time = time ( NULL ) ;
rc = 1 ;
}
}
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:12 +08:00
lock - > refreshing = 0 ;
curl_slist_free_all ( dav_headers ) ;
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:12 +08:00
return rc ;
}
2006-04-02 19:13:10 +08:00
static void check_locks ( void )
2006-03-11 12:18:12 +08:00
{
2009-03-19 07:43:53 +08:00
struct remote_lock * lock = repo - > locks ;
2006-03-11 12:18:12 +08:00
time_t current_time = time ( NULL ) ;
int time_remaining ;
while ( lock ) {
time_remaining = lock - > start_time + lock - > timeout -
current_time ;
if ( ! lock - > refreshing & & time_remaining < LOCK_REFRESH ) {
if ( ! refresh_lock ( lock ) ) {
fprintf ( stderr ,
" Unable to refresh lock for %s \n " ,
lock - > url ) ;
aborted = 1 ;
return ;
2006-03-08 08:13:20 +08:00
}
2005-11-05 06:22:35 +08:00
}
2006-03-11 12:18:12 +08:00
lock = lock - > next ;
2005-11-05 06:22:35 +08:00
}
2006-03-08 08:13:20 +08:00
}
2005-11-05 06:22:35 +08:00
2006-03-08 08:13:20 +08:00
static void release_request ( struct transfer_request * request )
{
struct transfer_request * entry = request_queue_head ;
if ( request = = request_queue_head ) {
request_queue_head = request - > next ;
} else {
while ( entry - > next ! = NULL & & entry - > next ! = request )
entry = entry - > next ;
if ( entry - > next = = request )
entry - > next = entry - > next - > next ;
}
Avoid unnecessary "if-before-free" tests.
This change removes all obvious useless if-before-free tests.
E.g., it replaces code like this:
if (some_expression)
free (some_expression);
with the now-equivalent:
free (some_expression);
It is equivalent not just because POSIX has required free(NULL)
to work for a long time, but simply because it has worked for
so long that no reasonable porting target fails the test.
Here's some evidence from nearly 1.5 years ago:
http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html
FYI, the change below was prepared by running the following:
git ls-files -z | xargs -0 \
perl -0x3b -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*NULL)?\s*\)\s+(free\s*\(\s*\1\s*\))/$2/s'
Note however, that it doesn't handle brace-enclosed blocks like
"if (x) { free (x); }". But that's ok, since there were none like
that in git sources.
Beware: if you do use the above snippet, note that it can
produce syntactically invalid C code. That happens when the
affected "if"-statement has a matching "else".
E.g., it would transform this
if (x)
free (x);
else
foo ();
into this:
free (x);
else
foo ();
There were none of those here, either.
If you're interested in automating detection of the useless
tests, you might like the useless-if-before-free script in gnulib:
[it *does* detect brace-enclosed free statements, and has a --name=S
option to make it detect free-like functions with different names]
http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=build-aux/useless-if-before-free
Addendum:
Remove one more (in imap-send.c), spotted by Jean-Luc Herren <jlh@gmx.ch>.
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-01 01:26:32 +08:00
free ( request - > url ) ;
2006-03-08 08:13:20 +08:00
free ( request ) ;
2005-11-05 06:22:35 +08:00
}
2005-11-03 03:19:24 +08:00
static void finish_request ( struct transfer_request * request )
{
2009-06-06 16:44:01 +08:00
struct http_pack_request * preq ;
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
struct http_object_request * obj_req ;
2006-03-11 12:18:18 +08:00
request - > curl_result = request - > slot - > curl_result ;
2005-11-03 03:19:24 +08:00
request - > http_code = request - > slot - > http_code ;
request - > slot = NULL ;
2005-11-05 06:22:35 +08:00
2006-03-08 08:13:20 +08:00
/* Keep locks active */
2006-03-11 12:18:12 +08:00
check_locks ( ) ;
2005-11-05 06:22:35 +08:00
2005-11-03 03:19:24 +08:00
if ( request - > headers ! = NULL )
curl_slist_free_all ( request - > headers ) ;
2005-11-19 03:03:25 +08:00
/* URL is reused for MOVE after PUT */
if ( request - > state ! = RUN_PUT ) {
free ( request - > url ) ;
request - > url = NULL ;
2006-03-08 08:13:20 +08:00
}
2005-11-19 03:03:25 +08:00
2006-03-08 08:13:20 +08:00
if ( request - > state = = RUN_MKCOL ) {
2005-11-03 03:19:24 +08:00
if ( request - > curl_result = = CURLE_OK | |
request - > http_code = = 405 ) {
2006-03-08 08:13:20 +08:00
remote_dir_exists [ request - > obj - > sha1 [ 0 ] ] = 1 ;
2005-11-03 03:19:24 +08:00
start_put ( request ) ;
} else {
fprintf ( stderr , " MKCOL %s failed, aborting (%d/%ld) \n " ,
2006-03-08 08:13:20 +08:00
sha1_to_hex ( request - > obj - > sha1 ) ,
2005-11-03 03:19:24 +08:00
request - > curl_result , request - > http_code ) ;
request - > state = ABORTED ;
aborted = 1 ;
}
} else if ( request - > state = = RUN_PUT ) {
if ( request - > curl_result = = CURLE_OK ) {
start_move ( request ) ;
} else {
fprintf ( stderr , " PUT %s failed, aborting (%d/%ld) \n " ,
2006-03-08 08:13:20 +08:00
sha1_to_hex ( request - > obj - > sha1 ) ,
2005-11-03 03:19:24 +08:00
request - > curl_result , request - > http_code ) ;
request - > state = ABORTED ;
aborted = 1 ;
}
} else if ( request - > state = = RUN_MOVE ) {
if ( request - > curl_result = = CURLE_OK ) {
2006-03-11 12:18:33 +08:00
if ( push_verbosely )
fprintf ( stderr , " sent %s \n " ,
sha1_to_hex ( request - > obj - > sha1 ) ) ;
2006-03-08 08:13:20 +08:00
request - > obj - > flags | = REMOTE ;
release_request ( request ) ;
2005-11-03 03:19:24 +08:00
} else {
fprintf ( stderr , " MOVE %s failed, aborting (%d/%ld) \n " ,
2006-03-08 08:13:20 +08:00
sha1_to_hex ( request - > obj - > sha1 ) ,
2005-11-03 03:19:24 +08:00
request - > curl_result , request - > http_code ) ;
request - > state = ABORTED ;
aborted = 1 ;
}
2006-03-11 12:18:18 +08:00
} else if ( request - > state = = RUN_FETCH_LOOSE ) {
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
obj_req = ( struct http_object_request * ) request - > userData ;
2006-03-11 12:18:18 +08:00
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
if ( finish_http_object_request ( obj_req ) = = 0 )
if ( obj_req - > rename = = 0 )
request - > obj - > flags | = ( LOCAL | REMOTE ) ;
2006-03-11 12:18:18 +08:00
/* Try fetching packed if necessary */
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
if ( request - > obj - > flags & LOCAL ) {
release_http_object_request ( obj_req ) ;
2006-03-11 12:18:18 +08:00
release_request ( request ) ;
http*: add helper methods for fetching objects (loose)
The code handling the fetching of loose objects in http-push.c and
http-walker.c have been refactored into new methods and a new struct
(object_http_request) in http.c. They are not meant to be invoked
elsewhere.
The new methods in http.c are
- new_http_object_request
- process_http_object_request
- finish_http_object_request
- abort_http_object_request
- release_http_object_request
and the new struct is http_object_request.
RANGER_HEADER_SIZE and no_pragma_header is no longer made available
outside of http.c, since after the above changes, there are no other
instances of usage outside of http.c.
Remove members of the transfer_request struct in http-push.c and
http-walker.c, including filename, real_sha1 and zret, as they are used
no longer used.
Move the methods append_remote_object_url() and get_remote_object_url()
from http-push.c to http.c. Additionally, get_remote_object_url() is no
longer defined only when USE_CURL_MULTI is defined, since
non-USE_CURL_MULTI code in http.c uses it (namely, in
new_http_object_request()).
Refactor code from http-push.c::start_fetch_loose() and
http-walker.c::start_object_fetch_request() that deals with the details
of coming up with the filename to store the retrieved object, resuming
a previously aborted request, and making a new curl request, into a new
function, new_http_object_request().
Refactor code from http-walker.c::process_object_request() into the
function, process_http_object_request().
Refactor code from http-push.c::finish_request() and
http-walker.c::finish_object_request() into a new function,
finish_http_object_request(). It returns the result of the
move_temp_to_file() invocation.
Add a function, release_http_object_request(), which cleans up object
request data. http-push.c and http-walker.c invoke this function
separately; http-push.c::release_request() and
http-walker.c::release_object_request() do not invoke this function.
Add a function, abort_http_object_request(), which unlink()s the object
file and invokes release_http_object_request(). Update
http-walker.c::abort_object_request() to use this.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-06 16:44:02 +08:00
} else
2006-03-11 12:18:18 +08:00
start_fetch_packed ( request ) ;
} else if ( request - > state = = RUN_FETCH_PACKED ) {
2009-06-06 16:44:01 +08:00
int fail = 1 ;
2006-03-11 12:18:18 +08:00
if ( request - > curl_result ! = CURLE_OK ) {
fprintf ( stderr , " Unable to get pack file %s \n %s " ,
request - > url , curl_errorstr ) ;
} else {
2009-06-06 16:44:01 +08:00
preq = ( struct http_pack_request * ) request - > userData ;
if ( preq ) {
2009-10-31 08:47:20 +08:00
if ( finish_http_pack_request ( preq ) = = 0 )
2009-06-06 16:44:01 +08:00
fail = 0 ;
release_http_pack_request ( preq ) ;
2006-03-11 12:18:18 +08:00
}
}
2009-06-06 16:44:01 +08:00
if ( fail )
repo - > can_update_info_refs = 0 ;
2006-03-11 12:18:18 +08:00
release_request ( request ) ;
2005-11-03 03:19:24 +08:00
}
}
2006-06-07 00:41:32 +08:00
# ifdef USE_CURL_MULTI
2009-06-06 16:43:27 +08:00
static int is_running_queue ;
2007-09-11 11:02:34 +08:00
static int fill_active_slot ( void * unused )
2005-11-03 03:19:24 +08:00
{
2009-03-16 05:01:20 +08:00
struct transfer_request * request ;
2005-11-03 03:19:24 +08:00
2009-06-06 16:43:27 +08:00
if ( aborted | | ! is_running_queue )
2007-09-11 11:02:28 +08:00
return 0 ;
2005-11-03 03:19:24 +08:00
2007-09-11 11:02:28 +08:00
for ( request = request_queue_head ; request ; request = request - > next ) {
2006-03-11 12:18:18 +08:00
if ( request - > state = = NEED_FETCH ) {
start_fetch_loose ( request ) ;
2007-09-11 11:02:28 +08:00
return 1 ;
2006-03-11 12:18:18 +08:00
} else if ( pushing & & request - > state = = NEED_PUSH ) {
2006-03-08 08:13:20 +08:00
if ( remote_dir_exists [ request - > obj - > sha1 [ 0 ] ] = = 1 ) {
2005-11-08 03:39:37 +08:00
start_put ( request ) ;
2006-03-08 08:13:20 +08:00
} else {
2005-11-08 03:39:37 +08:00
start_mkcol ( request ) ;
2006-03-08 08:13:20 +08:00
}
2007-09-11 11:02:28 +08:00
return 1 ;
2005-11-03 03:19:24 +08:00
}
2006-03-08 08:13:20 +08:00
}
2007-09-11 11:02:28 +08:00
return 0 ;
2005-11-03 03:19:24 +08:00
}
2006-06-07 00:41:32 +08:00
# endif
2005-11-03 03:19:24 +08:00
2006-03-08 08:13:20 +08:00
static void get_remote_object_list ( unsigned char parent ) ;
2006-03-11 12:18:18 +08:00
static void add_fetch_request ( struct object * obj )
{
struct transfer_request * request ;
check_locks ( ) ;
/*
* Don ' t fetch the object if it ' s known to exist locally
* or is already in the request queue
*/
if ( remote_dir_exists [ obj - > sha1 [ 0 ] ] = = - 1 )
get_remote_object_list ( obj - > sha1 [ 0 ] ) ;
if ( obj - > flags & ( LOCAL | FETCHING ) )
return ;
obj - > flags | = FETCHING ;
request = xmalloc ( sizeof ( * request ) ) ;
request - > obj = obj ;
request - > url = NULL ;
request - > lock = NULL ;
request - > headers = NULL ;
request - > state = NEED_FETCH ;
request - > next = request_queue_head ;
request_queue_head = request ;
2006-06-07 00:41:32 +08:00
# ifdef USE_CURL_MULTI
2006-03-11 12:18:18 +08:00
fill_active_slots ( ) ;
step_active_slots ( ) ;
2006-06-07 00:41:32 +08:00
# endif
2006-03-11 12:18:18 +08:00
}
2006-03-11 12:18:33 +08:00
static int add_send_request ( struct object * obj , struct remote_lock * lock )
2005-11-03 03:19:24 +08:00
{
2013-07-19 05:35:26 +08:00
struct transfer_request * request ;
2005-11-03 03:19:24 +08:00
struct packed_git * target ;
2006-03-11 12:18:12 +08:00
/* Keep locks active */
check_locks ( ) ;
2006-03-08 08:13:20 +08:00
/*
* Don ' t push the object if it ' s known to exist on the remote
* or is already in the request queue
*/
if ( remote_dir_exists [ obj - > sha1 [ 0 ] ] = = - 1 )
get_remote_object_list ( obj - > sha1 [ 0 ] ) ;
if ( obj - > flags & ( REMOTE | PUSHING ) )
2006-03-11 12:18:33 +08:00
return 0 ;
2009-03-19 07:43:53 +08:00
target = find_sha1_pack ( obj - > sha1 , repo - > packs ) ;
2006-03-08 08:13:20 +08:00
if ( target ) {
obj - > flags | = REMOTE ;
2006-03-11 12:18:33 +08:00
return 0 ;
2006-03-08 08:13:20 +08:00
}
2005-11-03 03:19:24 +08:00
2006-03-08 08:13:20 +08:00
obj - > flags | = PUSHING ;
2005-11-03 03:19:24 +08:00
request = xmalloc ( sizeof ( * request ) ) ;
2006-03-08 08:13:20 +08:00
request - > obj = obj ;
2005-11-03 03:19:24 +08:00
request - > url = NULL ;
2005-11-05 06:22:31 +08:00
request - > lock = lock ;
2005-11-03 03:19:24 +08:00
request - > headers = NULL ;
2006-03-08 08:13:20 +08:00
request - > state = NEED_PUSH ;
2005-11-05 06:22:18 +08:00
request - > next = request_queue_head ;
request_queue_head = request ;
2005-11-19 03:02:58 +08:00
2006-06-07 00:41:32 +08:00
# ifdef USE_CURL_MULTI
2005-11-19 03:02:58 +08:00
fill_active_slots ( ) ;
step_active_slots ( ) ;
2006-06-07 00:41:32 +08:00
# endif
2006-03-11 12:18:33 +08:00
return 1 ;
2005-11-03 03:19:24 +08:00
}
2005-11-09 06:18:31 +08:00
static int fetch_indices ( void )
2005-11-03 03:19:24 +08:00
{
2009-06-06 16:43:59 +08:00
int ret ;
2005-11-03 03:19:24 +08:00
if ( push_verbosely )
fprintf ( stderr , " Getting pack list \n " ) ;
2006-03-11 12:18:33 +08:00
2009-06-06 16:43:59 +08:00
switch ( http_get_info_packs ( repo - > url , & repo - > packs ) ) {
case HTTP_OK :
case HTTP_MISSING_TARGET :
ret = 0 ;
break ;
default :
ret = - 1 ;
2005-11-03 03:19:24 +08:00
}
2009-06-06 16:43:59 +08:00
return ret ;
2005-11-03 03:19:24 +08:00
}
2006-03-08 08:13:20 +08:00
static void one_remote_object ( const char * hex )
{
unsigned char sha1 [ 20 ] ;
struct object * obj ;
if ( get_sha1_hex ( hex , sha1 ) ! = 0 )
return ;
obj = lookup_object ( sha1 ) ;
if ( ! obj )
obj = parse_object ( sha1 ) ;
/* Ignore remote objects that don't exist locally */
if ( ! obj )
return ;
obj - > flags | = REMOTE ;
if ( ! object_list_contains ( objects , obj ) )
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
object_list_insert ( obj , & objects ) ;
2006-03-08 08:13:20 +08:00
}
2005-11-19 03:03:18 +08:00
static void handle_lockprop_ctx ( struct xml_ctx * ctx , int tag_closed )
2005-11-05 06:22:31 +08:00
{
2005-11-19 03:03:18 +08:00
int * lock_flags = ( int * ) ctx - > userData ;
if ( tag_closed ) {
if ( ! strcmp ( ctx - > name , DAV_CTX_LOCKENTRY ) ) {
if ( ( * lock_flags & DAV_PROP_LOCKEX ) & &
( * lock_flags & DAV_PROP_LOCKWR ) ) {
* lock_flags | = DAV_LOCK_OK ;
}
* lock_flags & = DAV_LOCK_OK ;
} else if ( ! strcmp ( ctx - > name , DAV_CTX_LOCKTYPE_WRITE ) ) {
* lock_flags | = DAV_PROP_LOCKWR ;
} else if ( ! strcmp ( ctx - > name , DAV_CTX_LOCKTYPE_EXCLUSIVE ) ) {
* lock_flags | = DAV_PROP_LOCKEX ;
}
}
2005-11-05 06:22:31 +08:00
}
2005-11-19 03:03:18 +08:00
static void handle_new_lock_ctx ( struct xml_ctx * ctx , int tag_closed )
2005-11-05 06:22:31 +08:00
{
2006-03-08 08:13:20 +08:00
struct remote_lock * lock = ( struct remote_lock * ) ctx - > userData ;
use a hash of the lock token as the suffix for PUT/MOVE
After 753bc91 ("Remove the requirement opaquelocktoken uri scheme"),
lock tokens are in the URI forms in which they are received from the
server, eg. 'opaquelocktoken:', 'urn:uuid:'.
However, "start_put" (and consequently "start_move"), which attempts to
create a unique temporary file using the UUID of the lock token,
inadvertently uses the lock token in its URI form. These file
operations on the server may not be successful (specifically, in
Windows), due to the colon ':' character from the URI form of the lock
token in the file path.
This patch uses a hash of the lock token instead, guaranteeing only
"safe" characters (a-f, 0-9) are used in the file path.
The token's hash is generated when the lock token is received from the
server in handle_new_lock_ctx, minimizing the number of times of
hashing.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-02-14 17:52:14 +08:00
git_SHA_CTX sha_ctx ;
unsigned char lock_token_sha1 [ 20 ] ;
2005-11-19 03:03:18 +08:00
if ( tag_closed & & ctx - > cdata ) {
if ( ! strcmp ( ctx - > name , DAV_ACTIVELOCK_OWNER ) ) {
lock - > owner = xmalloc ( strlen ( ctx - > cdata ) + 1 ) ;
strcpy ( lock - > owner , ctx - > cdata ) ;
} else if ( ! strcmp ( ctx - > name , DAV_ACTIVELOCK_TIMEOUT ) ) {
Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily. Leftover from this will be fixed in a separate step, including
idiotic conversions like
if (!strncmp("foo", arg, 3))
=>
if (!(-prefixcmp(arg, "foo")))
This was done by using this script in px.perl
#!/usr/bin/perl -i.bak -p
if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
}
if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
}
and running:
$ git grep -l strncmp -- '*.c' | xargs perl px.perl
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 17:53:29 +08:00
if ( ! prefixcmp ( ctx - > cdata , " Second- " ) )
2005-11-19 03:03:18 +08:00
lock - > timeout =
strtol ( ctx - > cdata + 7 , NULL , 10 ) ;
} else if ( ! strcmp ( ctx - > name , DAV_ACTIVELOCK_TOKEN ) ) {
2008-12-20 14:19:46 +08:00
lock - > token = xmalloc ( strlen ( ctx - > cdata ) + 1 ) ;
strcpy ( lock - > token , ctx - > cdata ) ;
use a hash of the lock token as the suffix for PUT/MOVE
After 753bc91 ("Remove the requirement opaquelocktoken uri scheme"),
lock tokens are in the URI forms in which they are received from the
server, eg. 'opaquelocktoken:', 'urn:uuid:'.
However, "start_put" (and consequently "start_move"), which attempts to
create a unique temporary file using the UUID of the lock token,
inadvertently uses the lock token in its URI form. These file
operations on the server may not be successful (specifically, in
Windows), due to the colon ':' character from the URI form of the lock
token in the file path.
This patch uses a hash of the lock token instead, guaranteeing only
"safe" characters (a-f, 0-9) are used in the file path.
The token's hash is generated when the lock token is received from the
server in handle_new_lock_ctx, minimizing the number of times of
hashing.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-02-14 17:52:14 +08:00
git_SHA1_Init ( & sha_ctx ) ;
git_SHA1_Update ( & sha_ctx , lock - > token , strlen ( lock - > token ) ) ;
git_SHA1_Final ( lock_token_sha1 , & sha_ctx ) ;
lock - > tmpfile_suffix [ 0 ] = ' _ ' ;
memcpy ( lock - > tmpfile_suffix + 1 , sha1_to_hex ( lock_token_sha1 ) , 40 ) ;
2005-11-19 03:03:18 +08:00
}
2005-11-05 06:22:31 +08:00
}
}
2011-05-03 23:47:28 +08:00
static void one_remote_ref ( const char * refname ) ;
2006-03-08 08:13:20 +08:00
2005-11-05 06:22:31 +08:00
static void
2005-11-19 03:03:18 +08:00
xml_start_tag ( void * userData , const char * name , const char * * atts )
2005-11-05 06:22:31 +08:00
{
2005-11-19 03:03:18 +08:00
struct xml_ctx * ctx = ( struct xml_ctx * ) userData ;
2006-04-12 00:37:58 +08:00
const char * c = strchr ( name , ' : ' ) ;
2005-11-19 03:03:18 +08:00
int new_len ;
if ( c = = NULL )
c = name ;
else
c + + ;
new_len = strlen ( ctx - > name ) + strlen ( c ) + 2 ;
if ( new_len > ctx - > len ) {
ctx - > name = xrealloc ( ctx - > name , new_len ) ;
ctx - > len = new_len ;
2005-11-05 06:22:31 +08:00
}
2005-11-19 03:03:18 +08:00
strcat ( ctx - > name , " . " ) ;
strcat ( ctx - > name , c ) ;
2005-11-05 06:22:31 +08:00
2006-08-28 12:19:39 +08:00
free ( ctx - > cdata ) ;
ctx - > cdata = NULL ;
2005-11-19 03:03:18 +08:00
ctx - > userFunc ( ctx , 0 ) ;
2005-11-05 06:22:31 +08:00
}
2005-11-03 03:19:24 +08:00
static void
2005-11-19 03:03:18 +08:00
xml_end_tag ( void * userData , const char * name )
2005-11-03 03:19:24 +08:00
{
2005-11-19 03:03:18 +08:00
struct xml_ctx * ctx = ( struct xml_ctx * ) userData ;
2006-04-12 00:37:58 +08:00
const char * c = strchr ( name , ' : ' ) ;
2005-11-19 03:03:18 +08:00
char * ep ;
2005-11-03 03:19:24 +08:00
2005-11-19 03:03:18 +08:00
ctx - > userFunc ( ctx , 1 ) ;
if ( c = = NULL )
c = name ;
else
c + + ;
ep = ctx - > name + strlen ( ctx - > name ) - strlen ( c ) - 1 ;
* ep = 0 ;
2005-11-03 03:19:24 +08:00
}
static void
2005-11-19 03:03:18 +08:00
xml_cdata ( void * userData , const XML_Char * s , int len )
2005-11-03 03:19:24 +08:00
{
2005-11-19 03:03:18 +08:00
struct xml_ctx * ctx = ( struct xml_ctx * ) userData ;
2006-08-28 12:19:39 +08:00
free ( ctx - > cdata ) ;
2007-09-16 06:32:36 +08:00
ctx - > cdata = xmemdupz ( s , len ) ;
2005-11-03 03:19:24 +08:00
}
2006-06-28 17:04:39 +08:00
static struct remote_lock * lock_remote ( const char * path , long timeout )
2005-11-03 03:19:24 +08:00
{
struct active_request_slot * slot ;
2006-03-11 12:18:01 +08:00
struct slot_results results ;
2007-12-10 03:30:59 +08:00
struct buffer out_buffer = { STRBUF_INIT , 0 } ;
struct strbuf in_buffer = STRBUF_INIT ;
2005-11-03 03:19:24 +08:00
char * url ;
2005-11-05 06:22:25 +08:00
char * ep ;
2005-11-03 03:19:24 +08:00
char timeout_header [ 25 ] ;
2006-03-11 12:18:12 +08:00
struct remote_lock * lock = NULL ;
2005-11-03 03:19:24 +08:00
struct curl_slist * dav_headers = NULL ;
2005-11-19 03:03:18 +08:00
struct xml_ctx ctx ;
2009-04-10 06:25:37 +08:00
char * escaped ;
2005-11-03 03:19:24 +08:00
2009-03-19 07:43:53 +08:00
url = xmalloc ( strlen ( repo - > url ) + strlen ( path ) + 1 ) ;
sprintf ( url , " %s%s " , repo - > url , path ) ;
2006-03-08 08:13:20 +08:00
2005-11-05 06:22:25 +08:00
/* Make sure leading directories exist for the remote ref */
2009-03-19 07:43:53 +08:00
ep = strchr ( url + strlen ( repo - > url ) + 1 , ' / ' ) ;
2005-11-05 06:22:25 +08:00
while ( ep ) {
2009-01-17 23:11:51 +08:00
char saved_character = ep [ 1 ] ;
ep [ 1 ] = ' \0 ' ;
2005-11-05 06:22:25 +08:00
slot = get_active_slot ( ) ;
2006-03-11 12:18:01 +08:00
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http_get ( slot - > curl , url , DAV_MKCOL ) ;
2005-11-05 06:22:25 +08:00
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
2006-03-11 12:18:01 +08:00
if ( results . curl_result ! = CURLE_OK & &
results . http_code ! = 405 ) {
2005-11-05 06:22:25 +08:00
fprintf ( stderr ,
" Unable to create branch path %s \n " ,
url ) ;
free ( url ) ;
return NULL ;
}
} else {
2006-03-11 12:18:33 +08:00
fprintf ( stderr , " Unable to start MKCOL request \n " ) ;
2005-11-05 06:22:25 +08:00
free ( url ) ;
return NULL ;
}
2009-01-17 23:11:51 +08:00
ep [ 1 ] = saved_character ;
2005-11-05 06:22:25 +08:00
ep = strchr ( ep + 1 , ' / ' ) ;
}
2012-05-22 07:09:47 +08:00
escaped = xml_entities ( ident_default_email ( ) ) ;
2009-04-10 06:25:37 +08:00
strbuf_addf ( & out_buffer . buf , LOCK_REQUEST , escaped ) ;
free ( escaped ) ;
2005-11-05 06:22:31 +08:00
2005-11-05 06:22:35 +08:00
sprintf ( timeout_header , " Timeout: Second-%ld " , timeout ) ;
2005-11-03 03:19:24 +08:00
dav_headers = curl_slist_append ( dav_headers , timeout_header ) ;
dav_headers = curl_slist_append ( dav_headers , " Content-Type: text/xml " ) ;
slot = get_active_slot ( ) ;
2006-03-11 12:18:01 +08:00
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http ( slot - > curl , url , DAV_LOCK , & out_buffer , fwrite_buffer ) ;
2005-11-03 03:19:24 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
2011-05-03 23:47:29 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_FILE , & in_buffer ) ;
2005-11-03 03:19:24 +08:00
2006-03-08 08:13:20 +08:00
lock = xcalloc ( 1 , sizeof ( * lock ) ) ;
lock - > timeout = - 1 ;
2005-11-19 03:03:18 +08:00
2005-11-03 03:19:24 +08:00
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
2006-03-11 12:18:01 +08:00
if ( results . curl_result = = CURLE_OK ) {
2007-12-12 06:50:21 +08:00
XML_Parser parser = XML_ParserCreate ( NULL ) ;
enum XML_Status result ;
2005-11-19 03:03:18 +08:00
ctx . name = xcalloc ( 10 , 1 ) ;
ctx . len = 0 ;
ctx . cdata = NULL ;
ctx . userFunc = handle_new_lock_ctx ;
2006-03-08 08:13:20 +08:00
ctx . userData = lock ;
2005-11-19 03:03:18 +08:00
XML_SetUserData ( parser , & ctx ) ;
XML_SetElementHandler ( parser , xml_start_tag ,
xml_end_tag ) ;
XML_SetCharacterDataHandler ( parser , xml_cdata ) ;
2007-12-10 03:30:59 +08:00
result = XML_Parse ( parser , in_buffer . buf ,
in_buffer . len , 1 ) ;
2005-11-19 03:03:18 +08:00
free ( ctx . name ) ;
if ( result ! = XML_STATUS_OK ) {
fprintf ( stderr , " XML error: %s \n " ,
XML_ErrorString (
XML_GetErrorCode ( parser ) ) ) ;
2006-03-08 08:13:20 +08:00
lock - > timeout = - 1 ;
2005-11-19 03:03:18 +08:00
}
2007-12-12 06:50:21 +08:00
XML_ParserFree ( parser ) ;
2005-11-03 03:19:24 +08:00
}
} else {
2006-03-11 12:18:33 +08:00
fprintf ( stderr , " Unable to start LOCK request \n " ) ;
2005-11-03 03:19:24 +08:00
}
2005-11-19 03:03:18 +08:00
curl_slist_free_all ( dav_headers ) ;
2007-12-10 03:30:59 +08:00
strbuf_release ( & out_buffer . buf ) ;
strbuf_release ( & in_buffer ) ;
2005-11-05 06:22:31 +08:00
2006-03-08 08:13:20 +08:00
if ( lock - > token = = NULL | | lock - > timeout < = 0 ) {
Avoid unnecessary "if-before-free" tests.
This change removes all obvious useless if-before-free tests.
E.g., it replaces code like this:
if (some_expression)
free (some_expression);
with the now-equivalent:
free (some_expression);
It is equivalent not just because POSIX has required free(NULL)
to work for a long time, but simply because it has worked for
so long that no reasonable porting target fails the test.
Here's some evidence from nearly 1.5 years ago:
http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html
FYI, the change below was prepared by running the following:
git ls-files -z | xargs -0 \
perl -0x3b -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*NULL)?\s*\)\s+(free\s*\(\s*\1\s*\))/$2/s'
Note however, that it doesn't handle brace-enclosed blocks like
"if (x) { free (x); }". But that's ok, since there were none like
that in git sources.
Beware: if you do use the above snippet, note that it can
produce syntactically invalid C code. That happens when the
affected "if"-statement has a matching "else".
E.g., it would transform this
if (x)
free (x);
else
foo ();
into this:
free (x);
else
foo ();
There were none of those here, either.
If you're interested in automating detection of the useless
tests, you might like the useless-if-before-free script in gnulib:
[it *does* detect brace-enclosed free statements, and has a --name=S
option to make it detect free-like functions with different names]
http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=build-aux/useless-if-before-free
Addendum:
Remove one more (in imap-send.c), spotted by Jean-Luc Herren <jlh@gmx.ch>.
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-01 01:26:32 +08:00
free ( lock - > token ) ;
free ( lock - > owner ) ;
2005-11-05 06:22:35 +08:00
free ( url ) ;
2006-03-08 08:13:20 +08:00
free ( lock ) ;
lock = NULL ;
2005-11-19 03:03:18 +08:00
} else {
2006-03-08 08:13:20 +08:00
lock - > url = url ;
lock - > start_time = time ( NULL ) ;
2009-03-19 07:43:53 +08:00
lock - > next = repo - > locks ;
repo - > locks = lock ;
2005-11-05 06:22:31 +08:00
}
2006-03-08 08:13:20 +08:00
return lock ;
2005-11-03 03:19:24 +08:00
}
2006-03-08 08:13:20 +08:00
static int unlock_remote ( struct remote_lock * lock )
2005-11-03 03:19:24 +08:00
{
struct active_request_slot * slot ;
2006-03-11 12:18:01 +08:00
struct slot_results results ;
2009-03-19 07:43:53 +08:00
struct remote_lock * prev = repo - > locks ;
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
struct curl_slist * dav_headers ;
2005-11-03 03:19:24 +08:00
int rc = 0 ;
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
dav_headers = get_dav_token_headers ( lock , DAV_HEADER_LOCK ) ;
2005-11-03 03:19:24 +08:00
slot = get_active_slot ( ) ;
2006-03-11 12:18:01 +08:00
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http_get ( slot - > curl , lock - > url , DAV_UNLOCK ) ;
2005-11-03 03:19:24 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
2006-03-11 12:18:01 +08:00
if ( results . curl_result = = CURLE_OK )
2005-11-03 03:19:24 +08:00
rc = 1 ;
else
2006-03-11 12:18:12 +08:00
fprintf ( stderr , " UNLOCK HTTP error %ld \n " ,
2006-03-11 12:18:01 +08:00
results . http_code ) ;
2005-11-03 03:19:24 +08:00
} else {
2006-03-11 12:18:12 +08:00
fprintf ( stderr , " Unable to start UNLOCK request \n " ) ;
2005-11-03 03:19:24 +08:00
}
curl_slist_free_all ( dav_headers ) ;
2005-11-05 06:22:35 +08:00
2009-03-19 07:43:53 +08:00
if ( repo - > locks = = lock ) {
repo - > locks = lock - > next ;
2006-03-11 12:18:12 +08:00
} else {
while ( prev & & prev - > next ! = lock )
prev = prev - > next ;
if ( prev )
prev - > next = prev - > next - > next ;
}
Avoid unnecessary "if-before-free" tests.
This change removes all obvious useless if-before-free tests.
E.g., it replaces code like this:
if (some_expression)
free (some_expression);
with the now-equivalent:
free (some_expression);
It is equivalent not just because POSIX has required free(NULL)
to work for a long time, but simply because it has worked for
so long that no reasonable porting target fails the test.
Here's some evidence from nearly 1.5 years ago:
http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html
FYI, the change below was prepared by running the following:
git ls-files -z | xargs -0 \
perl -0x3b -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*NULL)?\s*\)\s+(free\s*\(\s*\1\s*\))/$2/s'
Note however, that it doesn't handle brace-enclosed blocks like
"if (x) { free (x); }". But that's ok, since there were none like
that in git sources.
Beware: if you do use the above snippet, note that it can
produce syntactically invalid C code. That happens when the
affected "if"-statement has a matching "else".
E.g., it would transform this
if (x)
free (x);
else
foo ();
into this:
free (x);
else
foo ();
There were none of those here, either.
If you're interested in automating detection of the useless
tests, you might like the useless-if-before-free script in gnulib:
[it *does* detect brace-enclosed free statements, and has a --name=S
option to make it detect free-like functions with different names]
http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=build-aux/useless-if-before-free
Addendum:
Remove one more (in imap-send.c), spotted by Jean-Luc Herren <jlh@gmx.ch>.
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-01 01:26:32 +08:00
free ( lock - > owner ) ;
2006-03-11 12:18:12 +08:00
free ( lock - > url ) ;
free ( lock - > token ) ;
free ( lock ) ;
2005-11-03 03:19:24 +08:00
return rc ;
}
2008-05-26 02:27:44 +08:00
static void remove_locks ( void )
{
2009-03-19 07:43:53 +08:00
struct remote_lock * lock = repo - > locks ;
2008-05-26 02:27:44 +08:00
fprintf ( stderr , " Removing remote locks... \n " ) ;
while ( lock ) {
2009-05-24 21:16:49 +08:00
struct remote_lock * next = lock - > next ;
2008-05-26 02:27:44 +08:00
unlock_remote ( lock ) ;
2009-05-24 21:16:49 +08:00
lock = next ;
2008-05-26 02:27:44 +08:00
}
}
static void remove_locks_on_signal ( int signo )
{
remove_locks ( ) ;
chain kill signals for cleanup functions
If a piece of code wanted to do some cleanup before exiting
(e.g., cleaning up a lockfile or a tempfile), our usual
strategy was to install a signal handler that did something
like this:
do_cleanup(); /* actual work */
signal(signo, SIG_DFL); /* restore previous behavior */
raise(signo); /* deliver signal, killing ourselves */
For a single handler, this works fine. However, if we want
to clean up two _different_ things, we run into a problem.
The most recently installed handler will run, but when it
removes itself as a handler, it doesn't put back the first
handler.
This patch introduces sigchain, a tiny library for handling
a stack of signal handlers. You sigchain_push each handler,
and use sigchain_pop to restore whoever was before you in
the stack.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-22 14:02:35 +08:00
sigchain_pop ( signo ) ;
2008-05-26 02:27:44 +08:00
raise ( signo ) ;
}
2006-03-11 12:18:08 +08:00
static void remote_ls ( const char * path , int flags ,
void ( * userFunc ) ( struct remote_ls_ctx * ls ) ,
void * userData ) ;
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:08 +08:00
static void process_ls_object ( struct remote_ls_ctx * ls )
{
unsigned int * parent = ( unsigned int * ) ls - > userData ;
char * path = ls - > dentry_name ;
char * obj_hex ;
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:08 +08:00
if ( ! strcmp ( ls - > path , ls - > dentry_name ) & & ( ls - > flags & IS_DIR ) ) {
remote_dir_exists [ * parent ] = 1 ;
return ;
}
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:08 +08:00
if ( strlen ( path ) ! = 49 )
return ;
path + = 8 ;
obj_hex = xmalloc ( strlen ( path ) ) ;
2007-03-02 00:09:12 +08:00
/* NB: path is not null-terminated, can not use strlcpy here */
memcpy ( obj_hex , path , 2 ) ;
2006-03-11 12:18:08 +08:00
strcpy ( obj_hex + 2 , path + 3 ) ;
one_remote_object ( obj_hex ) ;
free ( obj_hex ) ;
}
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:08 +08:00
static void process_ls_ref ( struct remote_ls_ctx * ls )
{
if ( ! strcmp ( ls - > path , ls - > dentry_name ) & & ( ls - > dentry_flags & IS_DIR ) ) {
fprintf ( stderr , " %s \n " , ls - > dentry_name ) ;
return ;
}
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:08 +08:00
if ( ! ( ls - > dentry_flags & IS_DIR ) )
one_remote_ref ( ls - > dentry_name ) ;
}
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:08 +08:00
static void handle_remote_ls_ctx ( struct xml_ctx * ctx , int tag_closed )
{
struct remote_ls_ctx * ls = ( struct remote_ls_ctx * ) ctx - > userData ;
2006-03-08 08:13:20 +08:00
2006-03-11 12:18:08 +08:00
if ( tag_closed ) {
if ( ! strcmp ( ctx - > name , DAV_PROPFIND_RESP ) & & ls - > dentry_name ) {
if ( ls - > dentry_flags & IS_DIR ) {
2010-11-25 16:21:07 +08:00
/* ensure collection names end with slash */
str_end_url_with_slash ( ls - > dentry_name , & ls - > dentry_name ) ;
2006-03-11 12:18:08 +08:00
if ( ls - > flags & PROCESS_DIRS ) {
ls - > userFunc ( ls ) ;
}
if ( strcmp ( ls - > dentry_name , ls - > path ) & &
ls - > flags & RECURSIVE ) {
remote_ls ( ls - > dentry_name ,
ls - > flags ,
ls - > userFunc ,
ls - > userData ) ;
}
} else if ( ls - > flags & PROCESS_FILES ) {
ls - > userFunc ( ls ) ;
2006-03-08 08:13:20 +08:00
}
2006-03-11 12:18:08 +08:00
} else if ( ! strcmp ( ctx - > name , DAV_PROPFIND_NAME ) & & ctx - > cdata ) {
2008-12-23 16:31:15 +08:00
char * path = ctx - > cdata ;
if ( * ctx - > cdata = = ' h ' ) {
path = strstr ( path , " // " ) ;
if ( path ) {
path = strchr ( path + 2 , ' / ' ) ;
}
}
if ( path ) {
2010-11-25 16:21:08 +08:00
const char * url = repo - > url ;
if ( repo - > path )
url = repo - > path ;
if ( strncmp ( path , url , repo - > path_len ) )
2012-04-30 08:28:45 +08:00
error ( " Parsed path '%s' does not match url: '%s' " ,
2010-11-25 16:21:08 +08:00
path , url ) ;
else {
path + = repo - > path_len ;
ls - > dentry_name = xstrdup ( path ) ;
}
2008-12-23 16:31:15 +08:00
}
2006-03-11 12:18:08 +08:00
} else if ( ! strcmp ( ctx - > name , DAV_PROPFIND_COLLECTION ) ) {
ls - > dentry_flags | = IS_DIR ;
2006-03-08 08:13:20 +08:00
}
2006-03-11 12:18:08 +08:00
} else if ( ! strcmp ( ctx - > name , DAV_PROPFIND_RESP ) ) {
2006-08-28 12:19:39 +08:00
free ( ls - > dentry_name ) ;
2006-03-11 12:18:08 +08:00
ls - > dentry_name = NULL ;
ls - > dentry_flags = 0 ;
2006-03-08 08:13:20 +08:00
}
}
2009-01-17 23:36:26 +08:00
/*
* NEEDSWORK : remote_ls ( ) ignores info / refs on the remote side . But it
* should _only_ heed the information from that file , instead of trying to
* determine the refs from the remote file system ( badly : it does not even
* know about packed - refs ) .
*/
2006-03-11 12:18:08 +08:00
static void remote_ls ( const char * path , int flags ,
void ( * userFunc ) ( struct remote_ls_ctx * ls ) ,
void * userData )
2006-03-08 08:13:20 +08:00
{
2009-03-19 07:43:53 +08:00
char * url = xmalloc ( strlen ( repo - > url ) + strlen ( path ) + 1 ) ;
2006-03-08 08:13:20 +08:00
struct active_request_slot * slot ;
2006-03-11 12:18:01 +08:00
struct slot_results results ;
2007-12-10 03:30:59 +08:00
struct strbuf in_buffer = STRBUF_INIT ;
struct buffer out_buffer = { STRBUF_INIT , 0 } ;
2006-03-08 08:13:20 +08:00
struct curl_slist * dav_headers = NULL ;
struct xml_ctx ctx ;
2006-03-11 12:18:08 +08:00
struct remote_ls_ctx ls ;
ls . flags = flags ;
2006-09-02 12:16:31 +08:00
ls . path = xstrdup ( path ) ;
2006-03-11 12:18:08 +08:00
ls . dentry_name = NULL ;
ls . dentry_flags = 0 ;
ls . userData = userData ;
ls . userFunc = userFunc ;
2006-03-08 08:13:20 +08:00
2009-03-19 07:43:53 +08:00
sprintf ( url , " %s%s " , repo - > url , path ) ;
2006-03-08 08:13:20 +08:00
2007-12-10 03:30:59 +08:00
strbuf_addf ( & out_buffer . buf , PROPFIND_ALL_REQUEST ) ;
2006-03-08 08:13:20 +08:00
dav_headers = curl_slist_append ( dav_headers , " Depth: 1 " ) ;
dav_headers = curl_slist_append ( dav_headers , " Content-Type: text/xml " ) ;
slot = get_active_slot ( ) ;
2006-03-11 12:18:01 +08:00
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http ( slot - > curl , url , DAV_PROPFIND ,
& out_buffer , fwrite_buffer ) ;
2006-03-08 08:13:20 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
2011-05-03 23:47:29 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_FILE , & in_buffer ) ;
2006-03-08 08:13:20 +08:00
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
2006-03-11 12:18:01 +08:00
if ( results . curl_result = = CURLE_OK ) {
2007-12-12 06:50:21 +08:00
XML_Parser parser = XML_ParserCreate ( NULL ) ;
enum XML_Status result ;
2006-03-08 08:13:20 +08:00
ctx . name = xcalloc ( 10 , 1 ) ;
ctx . len = 0 ;
ctx . cdata = NULL ;
2006-03-11 12:18:08 +08:00
ctx . userFunc = handle_remote_ls_ctx ;
ctx . userData = & ls ;
2006-03-08 08:13:20 +08:00
XML_SetUserData ( parser , & ctx ) ;
XML_SetElementHandler ( parser , xml_start_tag ,
xml_end_tag ) ;
XML_SetCharacterDataHandler ( parser , xml_cdata ) ;
2007-12-10 03:30:59 +08:00
result = XML_Parse ( parser , in_buffer . buf ,
in_buffer . len , 1 ) ;
2006-03-08 08:13:20 +08:00
free ( ctx . name ) ;
if ( result ! = XML_STATUS_OK ) {
fprintf ( stderr , " XML error: %s \n " ,
XML_ErrorString (
XML_GetErrorCode ( parser ) ) ) ;
}
2007-12-12 06:50:21 +08:00
XML_ParserFree ( parser ) ;
2006-03-08 08:13:20 +08:00
}
} else {
2006-03-11 12:18:08 +08:00
fprintf ( stderr , " Unable to start PROPFIND request \n " ) ;
2006-03-08 08:13:20 +08:00
}
2006-03-11 12:18:08 +08:00
free ( ls . path ) ;
2006-03-08 08:13:20 +08:00
free ( url ) ;
2007-12-10 03:30:59 +08:00
strbuf_release ( & out_buffer . buf ) ;
strbuf_release ( & in_buffer ) ;
2006-03-08 08:13:20 +08:00
curl_slist_free_all ( dav_headers ) ;
}
2006-03-11 12:18:08 +08:00
static void get_remote_object_list ( unsigned char parent )
{
char path [ ] = " objects/XX/ " ;
static const char hex [ ] = " 0123456789abcdef " ;
unsigned int val = parent ;
path [ 8 ] = hex [ val > > 4 ] ;
path [ 9 ] = hex [ val & 0xf ] ;
remote_dir_exists [ val ] = 0 ;
remote_ls ( path , ( PROCESS_FILES | PROCESS_DIRS ) ,
process_ls_object , & val ) ;
}
2005-11-19 03:03:18 +08:00
static int locking_available ( void )
2005-11-03 03:19:24 +08:00
{
struct active_request_slot * slot ;
2006-03-11 12:18:01 +08:00
struct slot_results results ;
2007-12-10 03:30:59 +08:00
struct strbuf in_buffer = STRBUF_INIT ;
struct buffer out_buffer = { STRBUF_INIT , 0 } ;
2005-11-03 03:19:24 +08:00
struct curl_slist * dav_headers = NULL ;
2005-11-19 03:03:18 +08:00
struct xml_ctx ctx ;
int lock_flags = 0 ;
2009-04-10 06:25:37 +08:00
char * escaped ;
2005-11-03 03:19:24 +08:00
2009-04-10 06:25:37 +08:00
escaped = xml_entities ( repo - > url ) ;
strbuf_addf ( & out_buffer . buf , PROPFIND_SUPPORTEDLOCK_REQUEST , escaped ) ;
free ( escaped ) ;
2005-11-03 03:19:24 +08:00
dav_headers = curl_slist_append ( dav_headers , " Depth: 0 " ) ;
dav_headers = curl_slist_append ( dav_headers , " Content-Type: text/xml " ) ;
2006-03-11 12:18:01 +08:00
2005-11-03 03:19:24 +08:00
slot = get_active_slot ( ) ;
2006-03-11 12:18:01 +08:00
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http ( slot - > curl , repo - > url , DAV_PROPFIND ,
& out_buffer , fwrite_buffer ) ;
2005-11-03 03:19:24 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
2011-05-03 23:47:29 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_FILE , & in_buffer ) ;
2005-11-03 03:19:24 +08:00
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
2006-03-11 12:18:01 +08:00
if ( results . curl_result = = CURLE_OK ) {
2007-12-12 06:50:21 +08:00
XML_Parser parser = XML_ParserCreate ( NULL ) ;
enum XML_Status result ;
2005-11-19 03:03:18 +08:00
ctx . name = xcalloc ( 10 , 1 ) ;
ctx . len = 0 ;
ctx . cdata = NULL ;
ctx . userFunc = handle_lockprop_ctx ;
ctx . userData = & lock_flags ;
XML_SetUserData ( parser , & ctx ) ;
XML_SetElementHandler ( parser , xml_start_tag ,
xml_end_tag ) ;
2007-12-10 03:30:59 +08:00
result = XML_Parse ( parser , in_buffer . buf ,
in_buffer . len , 1 ) ;
2005-11-19 03:03:18 +08:00
free ( ctx . name ) ;
if ( result ! = XML_STATUS_OK ) {
fprintf ( stderr , " XML error: %s \n " ,
XML_ErrorString (
XML_GetErrorCode ( parser ) ) ) ;
lock_flags = 0 ;
}
2007-12-12 06:50:21 +08:00
XML_ParserFree ( parser ) ;
2008-01-21 07:00:54 +08:00
if ( ! lock_flags )
2009-03-24 09:09:09 +08:00
error ( " no DAV locking support on %s " ,
2009-03-19 07:43:53 +08:00
repo - > url ) ;
2008-01-21 07:00:54 +08:00
} else {
error ( " Cannot access URL %s, return code %d " ,
2009-03-19 07:43:53 +08:00
repo - > url , results . curl_result ) ;
2008-01-21 07:00:54 +08:00
lock_flags = 0 ;
2005-11-03 03:19:24 +08:00
}
} else {
2009-03-19 07:43:53 +08:00
error ( " Unable to start PROPFIND request on %s " , repo - > url ) ;
2005-11-03 03:19:24 +08:00
}
2007-12-10 03:30:59 +08:00
strbuf_release ( & out_buffer . buf ) ;
strbuf_release ( & in_buffer ) ;
2005-11-19 03:03:18 +08:00
curl_slist_free_all ( dav_headers ) ;
return lock_flags ;
2005-11-03 03:19:24 +08:00
}
2006-08-23 18:39:12 +08:00
static struct object_list * * add_one_object ( struct object * obj , struct object_list * * p )
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
{
struct object_list * entry = xmalloc ( sizeof ( struct object_list ) ) ;
entry - > item = obj ;
entry - > next = * p ;
* p = entry ;
return & entry - > next ;
}
2006-03-08 08:13:20 +08:00
static struct object_list * * process_blob ( struct blob * blob ,
struct object_list * * p ,
struct name_path * path ,
const char * name )
2005-11-03 03:19:24 +08:00
{
2006-03-08 08:13:20 +08:00
struct object * obj = & blob - > object ;
2005-11-03 03:19:24 +08:00
2006-03-08 08:13:20 +08:00
obj - > flags | = LOCAL ;
if ( obj - > flags & ( UNINTERESTING | SEEN ) )
return p ;
obj - > flags | = SEEN ;
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
return add_one_object ( obj , p ) ;
2006-03-08 08:13:20 +08:00
}
static struct object_list * * process_tree ( struct tree * tree ,
struct object_list * * p ,
struct name_path * path ,
const char * name )
{
struct object * obj = & tree - > object ;
2006-05-30 03:18:33 +08:00
struct tree_desc desc ;
tree_entry(): new tree-walking helper function
This adds a "tree_entry()" function that combines the common operation of
doing a "tree_entry_extract()" + "update_tree_entry()".
It also has a simplified calling convention, designed for simple loops
that traverse over a whole tree: the arguments are pointers to the tree
descriptor and a name_entry structure to fill in, and it returns a boolean
"true" if there was an entry left to be gotten in the tree.
This allows tree traversal with
struct tree_desc desc;
struct name_entry entry;
desc.buf = tree->buffer;
desc.size = tree->size;
while (tree_entry(&desc, &entry) {
... use "entry.{path, sha1, mode, pathlen}" ...
}
which is not only shorter than writing it out in full, it's hopefully less
error prone too.
[ It's actually a tad faster too - we don't need to recalculate the entry
pathlength in both extract and update, but need to do it only once.
Also, some callers can avoid doing a "strlen()" on the result, since
it's returned as part of the name_entry structure.
However, by now we're talking just 1% speedup on "git-rev-list --objects
--all", and we're definitely at the point where tree walking is no
longer the issue any more. ]
NOTE! Not everybody wants to use this new helper function, since some of
the tree walkers very much on purpose do the descriptor update separately
from the entry extraction. So the "extract + update" sequence still
remains as the core sequence, this is just a simplified interface.
We should probably add a silly two-line inline helper function for
initializing the descriptor from the "struct tree" too, just to cut down
on the noise from that common "desc" initializer.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-05-31 00:45:45 +08:00
struct name_entry entry ;
2006-03-08 08:13:20 +08:00
struct name_path me ;
obj - > flags | = LOCAL ;
if ( obj - > flags & ( UNINTERESTING | SEEN ) )
return p ;
if ( parse_tree ( tree ) < 0 )
die ( " bad tree object %s " , sha1_to_hex ( obj - > sha1 ) ) ;
obj - > flags | = SEEN ;
2006-09-02 12:16:31 +08:00
name = xstrdup ( name ) ;
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
p = add_one_object ( obj , p ) ;
2006-03-08 08:13:20 +08:00
me . up = path ;
me . elem = name ;
me . elem_len = strlen ( name ) ;
2006-05-30 03:18:33 +08:00
2007-03-22 01:08:25 +08:00
init_tree_desc ( & desc , tree - > buffer , tree - > size ) ;
2006-05-30 03:18:33 +08:00
2008-02-15 07:32:32 +08:00
while ( tree_entry ( & desc , & entry ) )
switch ( object_type ( entry . mode ) ) {
case OBJ_TREE :
tree_entry(): new tree-walking helper function
This adds a "tree_entry()" function that combines the common operation of
doing a "tree_entry_extract()" + "update_tree_entry()".
It also has a simplified calling convention, designed for simple loops
that traverse over a whole tree: the arguments are pointers to the tree
descriptor and a name_entry structure to fill in, and it returns a boolean
"true" if there was an entry left to be gotten in the tree.
This allows tree traversal with
struct tree_desc desc;
struct name_entry entry;
desc.buf = tree->buffer;
desc.size = tree->size;
while (tree_entry(&desc, &entry) {
... use "entry.{path, sha1, mode, pathlen}" ...
}
which is not only shorter than writing it out in full, it's hopefully less
error prone too.
[ It's actually a tad faster too - we don't need to recalculate the entry
pathlength in both extract and update, but need to do it only once.
Also, some callers can avoid doing a "strlen()" on the result, since
it's returned as part of the name_entry structure.
However, by now we're talking just 1% speedup on "git-rev-list --objects
--all", and we're definitely at the point where tree walking is no
longer the issue any more. ]
NOTE! Not everybody wants to use this new helper function, since some of
the tree walkers very much on purpose do the descriptor update separately
from the entry extraction. So the "extract + update" sequence still
remains as the core sequence, this is just a simplified interface.
We should probably add a silly two-line inline helper function for
initializing the descriptor from the "struct tree" too, just to cut down
on the noise from that common "desc" initializer.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-05-31 00:45:45 +08:00
p = process_tree ( lookup_tree ( entry . sha1 ) , p , & me , name ) ;
2008-02-15 07:32:32 +08:00
break ;
case OBJ_BLOB :
tree_entry(): new tree-walking helper function
This adds a "tree_entry()" function that combines the common operation of
doing a "tree_entry_extract()" + "update_tree_entry()".
It also has a simplified calling convention, designed for simple loops
that traverse over a whole tree: the arguments are pointers to the tree
descriptor and a name_entry structure to fill in, and it returns a boolean
"true" if there was an entry left to be gotten in the tree.
This allows tree traversal with
struct tree_desc desc;
struct name_entry entry;
desc.buf = tree->buffer;
desc.size = tree->size;
while (tree_entry(&desc, &entry) {
... use "entry.{path, sha1, mode, pathlen}" ...
}
which is not only shorter than writing it out in full, it's hopefully less
error prone too.
[ It's actually a tad faster too - we don't need to recalculate the entry
pathlength in both extract and update, but need to do it only once.
Also, some callers can avoid doing a "strlen()" on the result, since
it's returned as part of the name_entry structure.
However, by now we're talking just 1% speedup on "git-rev-list --objects
--all", and we're definitely at the point where tree walking is no
longer the issue any more. ]
NOTE! Not everybody wants to use this new helper function, since some of
the tree walkers very much on purpose do the descriptor update separately
from the entry extraction. So the "extract + update" sequence still
remains as the core sequence, this is just a simplified interface.
We should probably add a silly two-line inline helper function for
initializing the descriptor from the "struct tree" too, just to cut down
on the noise from that common "desc" initializer.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-05-31 00:45:45 +08:00
p = process_blob ( lookup_blob ( entry . sha1 ) , p , & me , name ) ;
2008-02-15 07:32:32 +08:00
break ;
default :
/* Subproject commit - not in this repository */
break ;
}
2006-05-30 03:18:33 +08:00
free ( tree - > buffer ) ;
tree - > buffer = NULL ;
2006-03-08 08:13:20 +08:00
return p ;
2005-11-03 03:19:24 +08:00
}
2006-03-11 12:18:33 +08:00
static int get_delta ( struct rev_info * revs , struct remote_lock * lock )
2005-11-03 03:19:24 +08:00
{
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
int i ;
2005-11-03 03:19:24 +08:00
struct commit * commit ;
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
struct object_list * * p = & objects ;
2006-03-11 12:18:33 +08:00
int count = 0 ;
2005-11-03 03:19:24 +08:00
2006-03-08 08:13:20 +08:00
while ( ( commit = get_revision ( revs ) ) ! = NULL ) {
p = process_tree ( commit - > tree , p , NULL , " " ) ;
commit - > object . flags | = LOCAL ;
if ( ! ( commit - > object . flags & UNINTERESTING ) )
2006-03-11 12:18:33 +08:00
count + = add_send_request ( & commit - > object , lock ) ;
2006-03-08 08:13:20 +08:00
}
2005-11-03 03:19:24 +08:00
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
for ( i = 0 ; i < revs - > pending . nr ; i + + ) {
struct object_array_entry * entry = revs - > pending . objects + i ;
struct object * obj = entry - > item ;
const char * name = entry - > name ;
2005-11-03 03:19:24 +08:00
2006-03-08 08:13:20 +08:00
if ( obj - > flags & ( UNINTERESTING | SEEN ) )
continue ;
2006-07-12 11:45:31 +08:00
if ( obj - > type = = OBJ_TAG ) {
2006-03-08 08:13:20 +08:00
obj - > flags | = SEEN ;
Add "named object array" concept
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-20 08:42:35 +08:00
p = add_one_object ( obj , p ) ;
2006-03-08 08:13:20 +08:00
continue ;
2005-11-03 03:19:24 +08:00
}
2006-07-12 11:45:31 +08:00
if ( obj - > type = = OBJ_TREE ) {
2006-03-08 08:13:20 +08:00
p = process_tree ( ( struct tree * ) obj , p , NULL , name ) ;
continue ;
2005-11-03 03:19:24 +08:00
}
2006-07-12 11:45:31 +08:00
if ( obj - > type = = OBJ_BLOB ) {
2006-03-08 08:13:20 +08:00
p = process_blob ( ( struct blob * ) obj , p , NULL , name ) ;
continue ;
2005-11-03 03:19:24 +08:00
}
2006-03-08 08:13:20 +08:00
die ( " unknown pending object %s (%s) " , sha1_to_hex ( obj - > sha1 ) , name ) ;
}
while ( objects ) {
if ( ! ( objects - > item - > flags & UNINTERESTING ) )
2006-03-11 12:18:33 +08:00
count + = add_send_request ( objects - > item , lock ) ;
2006-03-08 08:13:20 +08:00
objects = objects - > next ;
2005-11-03 03:19:24 +08:00
}
2006-03-11 12:18:33 +08:00
return count ;
2005-11-03 03:19:24 +08:00
}
2006-03-08 08:13:20 +08:00
static int update_remote ( unsigned char * sha1 , struct remote_lock * lock )
2005-11-03 03:19:24 +08:00
{
struct active_request_slot * slot ;
2006-03-11 12:18:01 +08:00
struct slot_results results ;
2007-12-10 03:30:59 +08:00
struct buffer out_buffer = { STRBUF_INIT , 0 } ;
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
struct curl_slist * dav_headers ;
2005-11-03 03:19:24 +08:00
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
dav_headers = get_dav_token_headers ( lock , DAV_HEADER_IF ) ;
2005-11-03 03:19:24 +08:00
2007-12-10 03:30:59 +08:00
strbuf_addf ( & out_buffer . buf , " %s \n " , sha1_to_hex ( sha1 ) ) ;
2005-11-03 03:19:24 +08:00
slot = get_active_slot ( ) ;
2006-03-11 12:18:01 +08:00
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http ( slot - > curl , lock - > url , DAV_PUT ,
& out_buffer , fwrite_null ) ;
2005-11-03 03:19:24 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
2007-12-10 03:30:59 +08:00
strbuf_release ( & out_buffer . buf ) ;
2006-03-11 12:18:01 +08:00
if ( results . curl_result ! = CURLE_OK ) {
2005-11-03 03:19:24 +08:00
fprintf ( stderr ,
" PUT error: curl result=%d, HTTP code=%ld \n " ,
2006-03-11 12:18:01 +08:00
results . curl_result , results . http_code ) ;
2005-11-03 03:19:24 +08:00
/* We should attempt recovery? */
return 0 ;
}
} else {
2007-12-10 03:30:59 +08:00
strbuf_release ( & out_buffer . buf ) ;
2005-11-03 03:19:24 +08:00
fprintf ( stderr , " Unable to start PUT request \n " ) ;
return 0 ;
}
return 1 ;
}
2009-05-31 22:26:48 +08:00
static struct ref * remote_refs ;
2006-03-08 08:13:20 +08:00
2011-05-03 23:47:28 +08:00
static void one_remote_ref ( const char * refname )
2006-03-08 08:13:20 +08:00
{
struct ref * ref ;
2006-03-11 12:18:18 +08:00
struct object * obj ;
2006-03-08 08:13:20 +08:00
2008-10-18 16:44:18 +08:00
ref = alloc_ref ( refname ) ;
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
2009-03-19 07:43:53 +08:00
if ( http_fetch_ref ( repo - > url , ref ) ! = 0 ) {
2006-03-08 08:13:20 +08:00
fprintf ( stderr ,
" Unable to fetch ref %s from %s \n " ,
2009-03-19 07:43:53 +08:00
refname , repo - > url ) ;
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
free ( ref ) ;
2006-03-08 08:13:20 +08:00
return ;
}
2006-03-11 12:18:18 +08:00
/*
* Fetch a copy of the object if it doesn ' t exist locally - it
* may be required for updating server info later .
*/
2009-03-19 07:43:53 +08:00
if ( repo - > can_update_info_refs & & ! has_sha1_file ( ref - > old_sha1 ) ) {
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
obj = lookup_unknown_object ( ref - > old_sha1 ) ;
2006-03-11 12:18:18 +08:00
if ( obj ) {
fprintf ( stderr , " fetch %s for %s \n " ,
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
sha1_to_hex ( ref - > old_sha1 ) , refname ) ;
2006-03-11 12:18:18 +08:00
add_fetch_request ( obj ) ;
}
}
2009-05-31 22:26:48 +08:00
ref - > next = remote_refs ;
remote_refs = ref ;
2006-03-08 08:13:20 +08:00
}
static void get_dav_remote_heads ( void )
{
2006-03-11 12:18:08 +08:00
remote_ls ( " refs/ " , ( PROCESS_FILES | PROCESS_DIRS | RECURSIVE ) , process_ls_ref , NULL ) ;
2006-03-08 08:13:20 +08:00
}
2006-03-11 12:18:18 +08:00
static void add_remote_info_ref ( struct remote_ls_ctx * ls )
{
2007-12-10 03:30:59 +08:00
struct strbuf * buf = ( struct strbuf * ) ls - > userData ;
2006-03-11 12:18:18 +08:00
struct object * o ;
int len ;
char * ref_info ;
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
struct ref * ref ;
2008-10-18 16:44:18 +08:00
ref = alloc_ref ( ls - > dentry_name ) ;
2006-03-11 12:18:18 +08:00
2009-03-19 07:43:53 +08:00
if ( http_fetch_ref ( repo - > url , ref ) ! = 0 ) {
2006-03-11 12:18:18 +08:00
fprintf ( stderr ,
" Unable to fetch ref %s from %s \n " ,
2009-03-19 07:43:53 +08:00
ls - > dentry_name , repo - > url ) ;
2006-03-11 12:18:18 +08:00
aborted = 1 ;
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
free ( ref ) ;
2006-03-11 12:18:18 +08:00
return ;
}
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
o = parse_object ( ref - > old_sha1 ) ;
2006-03-11 12:18:18 +08:00
if ( ! o ) {
fprintf ( stderr ,
" Unable to parse object %s for remote ref %s \n " ,
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
sha1_to_hex ( ref - > old_sha1 ) , ls - > dentry_name ) ;
2006-03-11 12:18:18 +08:00
aborted = 1 ;
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
free ( ref ) ;
2006-03-11 12:18:18 +08:00
return ;
}
len = strlen ( ls - > dentry_name ) + 42 ;
ref_info = xcalloc ( len + 1 , 1 ) ;
sprintf ( ref_info , " %s %s \n " ,
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
sha1_to_hex ( ref - > old_sha1 ) , ls - > dentry_name ) ;
2006-03-11 12:18:18 +08:00
fwrite_buffer ( ref_info , 1 , len , buf ) ;
free ( ref_info ) ;
2006-07-12 11:45:31 +08:00
if ( o - > type = = OBJ_TAG ) {
2006-03-11 12:18:18 +08:00
o = deref_tag ( o , ls - > dentry_name , 0 ) ;
if ( o ) {
len = strlen ( ls - > dentry_name ) + 45 ;
ref_info = xcalloc ( len + 1 , 1 ) ;
sprintf ( ref_info , " %s %s^{} \n " ,
sha1_to_hex ( o - > sha1 ) , ls - > dentry_name ) ;
fwrite_buffer ( ref_info , 1 , len , buf ) ;
free ( ref_info ) ;
}
}
Make walker.fetch_ref() take a struct ref.
This simplifies a few things, makes a few things slightly more
complicated, but, more importantly, allows that, when struct ref can
represent a symref, http_fetch_ref() can return one.
Incidentally makes the string that http_fetch_ref() gets include "refs/"
(if appropriate), because that's how the name field of struct ref works.
As far as I can tell, the usage in walker:interpret_target() wouldn't have
worked previously, if it ever would have been used, which it wouldn't
(since the fetch process uses the hash instead of the name of the ref
there).
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-27 03:53:09 +08:00
free ( ref ) ;
2006-03-11 12:18:18 +08:00
}
static void update_remote_info_refs ( struct remote_lock * lock )
{
2007-12-10 03:30:59 +08:00
struct buffer buffer = { STRBUF_INIT , 0 } ;
2006-03-11 12:18:18 +08:00
struct active_request_slot * slot ;
struct slot_results results ;
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
struct curl_slist * dav_headers ;
2006-03-11 12:18:18 +08:00
remote_ls ( " refs/ " , ( PROCESS_FILES | RECURSIVE ) ,
2007-12-10 03:30:59 +08:00
add_remote_info_ref , & buffer . buf ) ;
2006-03-11 12:18:18 +08:00
if ( ! aborted ) {
http-push: refactor lock-related headers creation for curl requests
DAV-related headers (more specifically, headers related to the lock token,
namely, If, Lock-Token, and Timeout) for curl requests are created and
allocated individually, eg a "if_header" variable for the "If: " header, a
"timeout_header" variable for the "Timeout: " header.
This patch provides a new function ("get_dav_token_headers") that creates
these header, saving methods from allocating memory, and from issuing a
"curl_slist_append()" call. The temporary string storage given to
curl_slist_append() is freed much earlier than the previous code with this
patch, but this change is safe, because curl_slist_append() keeps a copy
of the given string.
In part, this patch also addresses the fact that commit 753bc91 (Remove
the requirement opaquelocktoken uri scheme) did not update memory
allocations for DAV-related headers.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-24 10:00:22 +08:00
dav_headers = get_dav_token_headers ( lock , DAV_HEADER_IF ) ;
2006-03-11 12:18:18 +08:00
slot = get_active_slot ( ) ;
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http ( slot - > curl , lock - > url , DAV_PUT ,
& buffer , fwrite_null ) ;
2006-03-11 12:18:18 +08:00
curl_easy_setopt ( slot - > curl , CURLOPT_HTTPHEADER , dav_headers ) ;
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
if ( results . curl_result ! = CURLE_OK ) {
fprintf ( stderr ,
" PUT error: curl result=%d, HTTP code=%ld \n " ,
results . curl_result , results . http_code ) ;
}
}
}
2007-12-10 03:30:59 +08:00
strbuf_release ( & buffer . buf ) ;
2006-03-11 12:18:18 +08:00
}
static int remote_exists ( const char * path )
{
2009-03-19 07:43:53 +08:00
char * url = xmalloc ( strlen ( repo - > url ) + strlen ( path ) + 1 ) ;
2009-06-06 16:43:57 +08:00
int ret ;
2006-03-11 12:18:18 +08:00
2009-03-19 07:43:53 +08:00
sprintf ( url , " %s%s " , repo - > url , path ) ;
2006-03-11 12:18:18 +08:00
2013-02-01 05:02:07 +08:00
switch ( http_get_strbuf ( url , NULL , NULL , 0 ) ) {
2009-06-06 16:43:57 +08:00
case HTTP_OK :
ret = 1 ;
break ;
case HTTP_MISSING_TARGET :
ret = 0 ;
break ;
case HTTP_ERROR :
2013-04-06 06:22:31 +08:00
error ( " unable to access '%s': %s " , url , curl_errorstr ) ;
2009-06-06 16:43:57 +08:00
default :
ret = - 1 ;
2006-03-11 12:18:18 +08:00
}
2007-12-11 05:36:11 +08:00
free ( url ) ;
return ret ;
2006-03-11 12:18:18 +08:00
}
2006-06-28 17:04:39 +08:00
static void fetch_symref ( const char * path , char * * symref , unsigned char * sha1 )
2006-03-21 02:31:06 +08:00
{
char * url ;
2007-12-10 03:30:59 +08:00
struct strbuf buffer = STRBUF_INIT ;
2006-03-21 02:31:06 +08:00
2009-03-19 07:43:53 +08:00
url = xmalloc ( strlen ( repo - > url ) + strlen ( path ) + 1 ) ;
sprintf ( url , " %s%s " , repo - > url , path ) ;
2006-03-21 02:31:06 +08:00
2013-02-01 05:02:07 +08:00
if ( http_get_strbuf ( url , NULL , & buffer , 0 ) ! = HTTP_OK )
2009-06-06 16:43:58 +08:00
die ( " Couldn't get %s for remote symref \n %s " , url ,
curl_errorstr ) ;
2006-03-21 02:31:06 +08:00
free ( url ) ;
Avoid unnecessary "if-before-free" tests.
This change removes all obvious useless if-before-free tests.
E.g., it replaces code like this:
if (some_expression)
free (some_expression);
with the now-equivalent:
free (some_expression);
It is equivalent not just because POSIX has required free(NULL)
to work for a long time, but simply because it has worked for
so long that no reasonable porting target fails the test.
Here's some evidence from nearly 1.5 years ago:
http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html
FYI, the change below was prepared by running the following:
git ls-files -z | xargs -0 \
perl -0x3b -pi -e \
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*NULL)?\s*\)\s+(free\s*\(\s*\1\s*\))/$2/s'
Note however, that it doesn't handle brace-enclosed blocks like
"if (x) { free (x); }". But that's ok, since there were none like
that in git sources.
Beware: if you do use the above snippet, note that it can
produce syntactically invalid C code. That happens when the
affected "if"-statement has a matching "else".
E.g., it would transform this
if (x)
free (x);
else
foo ();
into this:
free (x);
else
foo ();
There were none of those here, either.
If you're interested in automating detection of the useless
tests, you might like the useless-if-before-free script in gnulib:
[it *does* detect brace-enclosed free statements, and has a --name=S
option to make it detect free-like functions with different names]
http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=build-aux/useless-if-before-free
Addendum:
Remove one more (in imap-send.c), spotted by Jean-Luc Herren <jlh@gmx.ch>.
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-01 01:26:32 +08:00
free ( * symref ) ;
2006-03-21 02:31:06 +08:00
* symref = NULL ;
2006-08-24 04:57:23 +08:00
hashclr ( sha1 ) ;
2006-03-21 02:31:06 +08:00
2007-12-10 03:30:59 +08:00
if ( buffer . len = = 0 )
2006-03-21 02:31:06 +08:00
return ;
/* If it's a symref, set the refname; otherwise try for a sha1 */
2007-12-10 03:30:59 +08:00
if ( ! prefixcmp ( ( char * ) buffer . buf , " ref: " ) ) {
* symref = xmemdupz ( ( char * ) buffer . buf + 5 , buffer . len - 6 ) ;
2006-03-21 02:31:06 +08:00
} else {
2007-12-10 03:30:59 +08:00
get_sha1_hex ( buffer . buf , sha1 ) ;
2006-03-21 02:31:06 +08:00
}
2007-12-10 03:30:59 +08:00
strbuf_release ( & buffer ) ;
2006-03-21 02:31:06 +08:00
}
2011-09-17 19:57:45 +08:00
static int verify_merge_base ( unsigned char * head_sha1 , struct ref * remote )
2006-03-21 02:31:06 +08:00
{
2011-09-17 19:57:45 +08:00
struct commit * head = lookup_commit_or_die ( head_sha1 , " HEAD " ) ;
struct commit * branch = lookup_commit_or_die ( remote - > old_sha1 , remote - > name ) ;
2006-03-21 02:31:06 +08:00
2012-08-28 06:21:37 +08:00
return in_merge_bases ( branch , head ) ;
2006-03-21 02:31:06 +08:00
}
2011-05-03 23:47:28 +08:00
static int delete_remote_branch ( const char * pattern , int force )
2006-03-21 02:31:06 +08:00
{
struct ref * refs = remote_refs ;
struct ref * remote_ref = NULL ;
unsigned char head_sha1 [ 20 ] ;
char * symref = NULL ;
int match ;
int patlen = strlen ( pattern ) ;
int i ;
struct active_request_slot * slot ;
struct slot_results results ;
char * url ;
/* Find the remote branch(es) matching the specified branch name */
for ( match = 0 ; refs ; refs = refs - > next ) {
char * name = refs - > name ;
int namelen = strlen ( name ) ;
if ( namelen < patlen | |
memcmp ( name + namelen - patlen , pattern , patlen ) )
continue ;
if ( namelen ! = patlen & & name [ namelen - patlen - 1 ] ! = ' / ' )
continue ;
match + + ;
remote_ref = refs ;
}
if ( match = = 0 )
return error ( " No remote branch matches %s " , pattern ) ;
if ( match ! = 1 )
return error ( " More than one remote branch matches %s " ,
pattern ) ;
/*
* Remote HEAD must be a symref ( not exactly foolproof ; a remote
* symlink to a symref will look like a symref )
*/
fetch_symref ( " HEAD " , & symref , head_sha1 ) ;
if ( ! symref )
return error ( " Remote HEAD is not a symref " ) ;
/* Remote branch must not be the remote HEAD */
2011-08-26 05:46:52 +08:00
for ( i = 0 ; symref & & i < MAXDEPTH ; i + + ) {
2006-03-21 02:31:06 +08:00
if ( ! strcmp ( remote_ref - > name , symref ) )
return error ( " Remote branch %s is the current HEAD " ,
remote_ref - > name ) ;
fetch_symref ( symref , & symref , head_sha1 ) ;
}
/* Run extra sanity checks if delete is not forced */
if ( ! force ) {
/* Remote HEAD must resolve to a known object */
if ( symref )
return error ( " Remote HEAD symrefs too deep " ) ;
2009-05-31 18:36:10 +08:00
if ( is_null_sha1 ( head_sha1 ) )
2006-03-21 02:31:06 +08:00
return error ( " Unable to resolve remote HEAD " ) ;
if ( ! has_sha1_file ( head_sha1 ) )
return error ( " Remote HEAD resolves to object %s \n which does not exist locally, perhaps you need to fetch? " , sha1_to_hex ( head_sha1 ) ) ;
/* Remote branch must resolve to a known object */
2009-05-31 18:36:10 +08:00
if ( is_null_sha1 ( remote_ref - > old_sha1 ) )
2006-03-21 02:31:06 +08:00
return error ( " Unable to resolve remote branch %s " ,
remote_ref - > name ) ;
if ( ! has_sha1_file ( remote_ref - > old_sha1 ) )
return error ( " Remote branch %s resolves to object %s \n which does not exist locally, perhaps you need to fetch? " , remote_ref - > name , sha1_to_hex ( remote_ref - > old_sha1 ) ) ;
/* Remote branch must be an ancestor of remote HEAD */
2011-09-17 19:57:45 +08:00
if ( ! verify_merge_base ( head_sha1 , remote_ref ) ) {
2007-11-03 10:39:44 +08:00
return error ( " The branch '%s' is not an ancestor "
" of your current HEAD. \n "
" If you are sure you want to delete it, "
" run: \n \t 'git http-push -D %s %s' " ,
2009-03-19 07:43:53 +08:00
remote_ref - > name , repo - > url , pattern ) ;
2006-03-21 02:31:06 +08:00
}
}
/* Send delete request */
fprintf ( stderr , " Removing remote branch '%s' \n " , remote_ref - > name ) ;
2008-02-28 03:27:53 +08:00
if ( dry_run )
return 0 ;
2009-03-19 07:43:53 +08:00
url = xmalloc ( strlen ( repo - > url ) + strlen ( remote_ref - > name ) + 1 ) ;
sprintf ( url , " %s%s " , repo - > url , remote_ref - > name ) ;
2006-03-21 02:31:06 +08:00
slot = get_active_slot ( ) ;
slot - > results = & results ;
2011-05-03 23:47:29 +08:00
curl_setup_http_get ( slot - > curl , url , DAV_DELETE ) ;
2006-03-21 02:31:06 +08:00
if ( start_active_slot ( slot ) ) {
run_active_slot ( slot ) ;
free ( url ) ;
if ( results . curl_result ! = CURLE_OK )
2012-04-30 08:28:45 +08:00
return error ( " DELETE request failed (%d/%ld) " ,
2006-03-21 02:31:06 +08:00
results . curl_result , results . http_code ) ;
} else {
free ( url ) ;
return error ( " Unable to start DELETE request " ) ;
}
return 0 ;
}
2009-06-19 01:28:43 +08:00
static void run_request_queue ( void )
2009-06-06 16:43:27 +08:00
{
# ifdef USE_CURL_MULTI
is_running_queue = 1 ;
fill_active_slots ( ) ;
add_fill_function ( NULL , fill_active_slot ) ;
# endif
do {
finish_all_active_slots ( ) ;
# ifdef USE_CURL_MULTI
fill_active_slots ( ) ;
# endif
} while ( request_queue_head & & ! aborted ) ;
# ifdef USE_CURL_MULTI
is_running_queue = 0 ;
# endif
}
2005-11-03 03:19:24 +08:00
int main ( int argc , char * * argv )
{
struct transfer_request * request ;
struct transfer_request * next_request ;
int nr_refspec = 0 ;
char * * refspec = NULL ;
2006-03-11 12:18:12 +08:00
struct remote_lock * ref_lock = NULL ;
2006-03-11 12:18:18 +08:00
struct remote_lock * info_ref_lock = NULL ;
2006-03-08 08:13:20 +08:00
struct rev_info revs ;
2006-03-21 02:31:06 +08:00
int delete_branch = 0 ;
int force_delete = 0 ;
2006-03-11 12:18:33 +08:00
int objects_to_send ;
2005-11-03 03:19:24 +08:00
int rc = 0 ;
int i ;
2006-03-22 07:49:05 +08:00
int new_refs ;
2009-02-25 16:32:11 +08:00
struct ref * ref , * local_refs ;
2005-11-03 03:19:24 +08:00
i18n: add infrastructure for translating Git with gettext
Change the skeleton implementation of i18n in Git to one that can show
localized strings to users for our C, Shell and Perl programs using
either GNU libintl or the Solaris gettext implementation.
This new internationalization support is enabled by default. If
gettext isn't available, or if Git is compiled with
NO_GETTEXT=YesPlease, Git falls back on its current behavior of
showing interface messages in English. When using the autoconf script
we'll auto-detect if the gettext libraries are installed and act
appropriately.
This change is somewhat large because as well as adding a C, Shell and
Perl i18n interface we're adding a lot of tests for them, and for
those tests to work we need a skeleton PO file to actually test
translations. A minimal Icelandic translation is included for this
purpose. Icelandic includes multi-byte characters which makes it easy
to test various edge cases, and it's a language I happen to
understand.
The rest of the commit message goes into detail about various
sub-parts of this commit.
= Installation
Gettext .mo files will be installed and looked for in the standard
$(prefix)/share/locale path. GIT_TEXTDOMAINDIR can also be set to
override that, but that's only intended to be used to test Git itself.
= Perl
Perl code that's to be localized should use the new Git::I18n
module. It imports a __ function into the caller's package by default.
Instead of using the high level Locale::TextDomain interface I've
opted to use the low-level (equivalent to the C interface)
Locale::Messages module, which Locale::TextDomain itself uses.
Locale::TextDomain does a lot of redundant work we don't need, and
some of it would potentially introduce bugs. It tries to set the
$TEXTDOMAIN based on package of the caller, and has its own
hardcoded paths where it'll search for messages.
I found it easier just to completely avoid it rather than try to
circumvent its behavior. In any case, this is an issue wholly
internal Git::I18N. Its guts can be changed later if that's deemed
necessary.
See <AANLkTilYD_NyIZMyj9dHtVk-ylVBfvyxpCC7982LWnVd@mail.gmail.com> for
a further elaboration on this topic.
= Shell
Shell code that's to be localized should use the git-sh-i18n
library. It's basically just a wrapper for the system's gettext.sh.
If gettext.sh isn't available we'll fall back on gettext(1) if it's
available. The latter is available without the former on Solaris,
which has its own non-GNU gettext implementation. We also need to
emulate eval_gettext() there.
If neither are present we'll use a dumb printf(1) fall-through
wrapper.
= About libcharset.h and langinfo.h
We use libcharset to query the character set of the current locale if
it's available. I.e. we'll use it instead of nl_langinfo if
HAVE_LIBCHARSET_H is set.
The GNU gettext manual recommends using langinfo.h's
nl_langinfo(CODESET) to acquire the current character set, but on
systems that have libcharset.h's locale_charset() using the latter is
either saner, or the only option on those systems.
GNU and Solaris have a nl_langinfo(CODESET), FreeBSD can use either,
but MinGW and some others need to use libcharset.h's locale_charset()
instead.
=Credits
This patch is based on work by Jeff Epler <jepler@unpythonic.net> who
did the initial Makefile / C work, and a lot of comments from the Git
mailing list, including Jonathan Nieder, Jakub Narebski, Johannes
Sixt, Erik Faye-Lund, Peter Krefting, Junio C Hamano, Thomas Rast and
others.
[jc: squashed a small Makefile fix from Ramsay]
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-11-18 07:14:42 +08:00
git_setup_gettext ( ) ;
2009-01-18 20:00:12 +08:00
git_extract_argv0_path ( argv [ 0 ] ) ;
2009-03-19 07:43:53 +08:00
repo = xcalloc ( sizeof ( * repo ) , 1 ) ;
2005-11-03 03:19:24 +08:00
argv + + ;
for ( i = 1 ; i < argc ; i + + , argv + + ) {
char * arg = * argv ;
if ( * arg = = ' - ' ) {
2006-03-08 08:13:20 +08:00
if ( ! strcmp ( arg , " --all " ) ) {
2007-11-10 07:32:10 +08:00
push_all = MATCH_REFS_ALL ;
2005-11-03 03:19:24 +08:00
continue ;
}
if ( ! strcmp ( arg , " --force " ) ) {
force_all = 1 ;
continue ;
}
2007-10-16 12:35:22 +08:00
if ( ! strcmp ( arg , " --dry-run " ) ) {
dry_run = 1 ;
continue ;
}
2009-10-31 08:47:30 +08:00
if ( ! strcmp ( arg , " --helper-status " ) ) {
helper_status = 1 ;
continue ;
}
2005-11-03 03:19:24 +08:00
if ( ! strcmp ( arg , " --verbose " ) ) {
push_verbosely = 1 ;
2009-06-06 16:43:41 +08:00
http_is_verbose = 1 ;
2005-11-03 03:19:24 +08:00
continue ;
}
2006-03-21 02:31:06 +08:00
if ( ! strcmp ( arg , " -d " ) ) {
delete_branch = 1 ;
continue ;
}
if ( ! strcmp ( arg , " -D " ) ) {
delete_branch = 1 ;
force_delete = 1 ;
continue ;
}
2009-11-09 18:47:34 +08:00
if ( ! strcmp ( arg , " -h " ) )
usage ( http_push_usage ) ;
2005-11-03 03:19:24 +08:00
}
2009-03-19 07:43:53 +08:00
if ( ! repo - > url ) {
2006-03-08 08:13:20 +08:00
char * path = strstr ( arg , " // " ) ;
2010-11-25 16:21:09 +08:00
str_end_url_with_slash ( arg , & repo - > url ) ;
repo - > path_len = strlen ( repo - > url ) ;
2006-03-08 08:13:20 +08:00
if ( path ) {
2009-03-19 07:43:53 +08:00
repo - > path = strchr ( path + 2 , ' / ' ) ;
if ( repo - > path )
repo - > path_len = strlen ( repo - > path ) ;
2006-03-08 08:13:20 +08:00
}
2005-11-03 03:19:24 +08:00
continue ;
}
refspec = argv ;
nr_refspec = argc - i ;
break ;
}
2008-01-14 03:02:59 +08:00
# ifndef USE_CURL_MULTI
die ( " git-push is not available for http/https repository when not compiled with USE_CURL_MULTI " ) ;
# endif
2009-03-19 07:43:53 +08:00
if ( ! repo - > url )
2005-11-30 01:33:36 +08:00
usage ( http_push_usage ) ;
2006-03-21 02:31:06 +08:00
if ( delete_branch & & nr_refspec ! = 1 )
die ( " You must specify only one branch name when deleting a remote branch " ) ;
2009-11-09 18:47:34 +08:00
setup_git_directory ( ) ;
2006-03-08 08:13:20 +08:00
memset ( remote_dir_exists , - 1 , 256 ) ;
2005-11-08 03:39:37 +08:00
2011-12-14 08:11:56 +08:00
http_init ( NULL , repo - > url , 1 ) ;
2005-11-03 03:19:24 +08:00
2009-06-06 16:43:31 +08:00
# ifdef USE_CURL_MULTI
2009-06-06 16:43:27 +08:00
is_running_queue = 0 ;
2009-06-06 16:43:31 +08:00
# endif
2009-06-06 16:43:27 +08:00
2005-11-03 03:19:24 +08:00
/* Verify DAV compliance/lock support */
2005-11-19 03:03:18 +08:00
if ( ! locking_available ( ) ) {
2005-11-03 03:19:24 +08:00
rc = 1 ;
goto cleanup ;
}
2009-01-22 14:03:08 +08:00
sigchain_push_common ( remove_locks_on_signal ) ;
2008-05-26 02:27:44 +08:00
2006-03-11 12:18:18 +08:00
/* Check whether the remote has server info files */
2009-03-19 07:43:53 +08:00
repo - > can_update_info_refs = 0 ;
repo - > has_info_refs = remote_exists ( " info/refs " ) ;
repo - > has_info_packs = remote_exists ( " objects/info/packs " ) ;
if ( repo - > has_info_refs ) {
2006-03-11 12:18:18 +08:00
info_ref_lock = lock_remote ( " info/refs " , LOCK_TIME ) ;
if ( info_ref_lock )
2009-03-19 07:43:53 +08:00
repo - > can_update_info_refs = 1 ;
2008-01-19 23:22:48 +08:00
else {
2009-03-24 09:09:09 +08:00
error ( " cannot lock existing info/refs " ) ;
2008-01-19 23:22:48 +08:00
rc = 1 ;
goto cleanup ;
}
2006-03-11 12:18:18 +08:00
}
2009-03-19 07:43:53 +08:00
if ( repo - > has_info_packs )
2006-03-11 12:18:18 +08:00
fetch_indices ( ) ;
2006-03-08 08:13:20 +08:00
/* Get a list of all local and remote heads to validate refspecs */
2009-02-25 16:32:11 +08:00
local_refs = get_local_heads ( ) ;
2006-03-08 08:13:20 +08:00
fprintf ( stderr , " Fetching remote heads... \n " ) ;
get_dav_remote_heads ( ) ;
2009-06-06 16:43:27 +08:00
run_request_queue ( ) ;
2006-03-08 08:13:20 +08:00
2006-03-21 02:31:06 +08:00
/* Remove a remote branch if -d or -D was specified */
if ( delete_branch ) {
2009-10-31 08:47:30 +08:00
if ( delete_remote_branch ( refspec [ 0 ] , force_delete ) = = - 1 ) {
2006-03-21 02:31:06 +08:00
fprintf ( stderr , " Unable to delete remote branch %s \n " ,
refspec [ 0 ] ) ;
2009-10-31 08:47:30 +08:00
if ( helper_status )
printf ( " error %s cannot remove \n " , refspec [ 0 ] ) ;
}
2006-03-21 02:31:06 +08:00
goto cleanup ;
}
2006-03-08 08:13:20 +08:00
/* match them up */
2011-09-10 02:54:58 +08:00
if ( match_push_refs ( local_refs , & remote_refs ,
nr_refspec , ( const char * * ) refspec , push_all ) ) {
2008-01-19 23:22:47 +08:00
rc = - 1 ;
goto cleanup ;
}
2006-03-08 08:13:20 +08:00
if ( ! remote_refs ) {
fprintf ( stderr , " No refs in common and none specified; doing nothing. \n " ) ;
2009-10-31 08:47:30 +08:00
if ( helper_status )
printf ( " error null no match \n " ) ;
2008-01-19 23:22:47 +08:00
rc = 0 ;
goto cleanup ;
2006-03-08 08:13:20 +08:00
}
2006-03-22 07:49:05 +08:00
new_refs = 0 ;
2006-03-08 08:13:20 +08:00
for ( ref = remote_refs ; ref ; ref = ref - > next ) {
char old_hex [ 60 ] , * new_hex ;
2009-05-21 17:32:44 +08:00
const char * commit_argv [ 5 ] ;
2006-03-22 07:49:05 +08:00
int commit_argc ;
char * new_sha1_hex , * old_sha1_hex ;
2006-03-08 08:13:20 +08:00
if ( ! ref - > peer_ref )
continue ;
2008-02-28 03:27:53 +08:00
2009-05-31 18:36:10 +08:00
if ( is_null_sha1 ( ref - > peer_ref - > new_sha1 ) ) {
2008-02-28 03:27:53 +08:00
if ( delete_remote_branch ( ref - > name , 1 ) = = - 1 ) {
error ( " Could not remove %s " , ref - > name ) ;
2009-10-31 08:47:30 +08:00
if ( helper_status )
printf ( " error %s cannot remove \n " , ref - > name ) ;
2008-02-28 03:27:53 +08:00
rc = - 4 ;
}
2009-10-31 08:47:30 +08:00
else if ( helper_status )
printf ( " ok %s \n " , ref - > name ) ;
2008-02-28 03:27:53 +08:00
new_refs + + ;
continue ;
}
2006-08-18 02:54:57 +08:00
if ( ! hashcmp ( ref - > old_sha1 , ref - > peer_ref - > new_sha1 ) ) {
2010-03-02 18:49:27 +08:00
if ( push_verbosely )
2006-03-08 08:13:20 +08:00
fprintf ( stderr , " '%s': up-to-date \n " , ref - > name ) ;
2009-10-31 08:47:30 +08:00
if ( helper_status )
printf ( " ok %s up to date \n " , ref - > name ) ;
2006-03-08 08:13:20 +08:00
continue ;
}
if ( ! force_all & &
2009-05-31 18:36:10 +08:00
! is_null_sha1 ( ref - > old_sha1 ) & &
2006-03-08 08:13:20 +08:00
! ref - > force ) {
if ( ! has_sha1_file ( ref - > old_sha1 ) | |
! ref_newer ( ref - > peer_ref - > new_sha1 ,
ref - > old_sha1 ) ) {
2007-11-03 10:39:44 +08:00
/*
* We do not have the remote ref , or
2006-03-08 08:13:20 +08:00
* we know that the remote ref is not
* an ancestor of what we are trying to
* push . Either way this can be losing
* commits at the remote end and likely
* we were not up to date to begin with .
*/
2007-11-03 10:39:44 +08:00
error ( " remote '%s' is not an ancestor of \n "
" local '%s'. \n "
" Maybe you are not up-to-date and "
2006-03-08 08:13:20 +08:00
" need to pull first? " ,
ref - > name ,
ref - > peer_ref - > name ) ;
2009-10-31 08:47:30 +08:00
if ( helper_status )
printf ( " error %s non-fast forward \n " , ref - > name ) ;
2006-03-11 12:18:33 +08:00
rc = - 2 ;
2006-03-08 08:13:20 +08:00
continue ;
}
2005-11-03 03:19:24 +08:00
}
2006-08-23 14:49:00 +08:00
hashcpy ( ref - > new_sha1 , ref - > peer_ref - > new_sha1 ) ;
2006-03-08 08:13:20 +08:00
new_refs + + ;
strcpy ( old_hex , sha1_to_hex ( ref - > old_sha1 ) ) ;
new_hex = sha1_to_hex ( ref - > new_sha1 ) ;
fprintf ( stderr , " updating '%s' " , ref - > name ) ;
if ( strcmp ( ref - > name , ref - > peer_ref - > name ) )
fprintf ( stderr , " using '%s' " , ref - > peer_ref - > name ) ;
fprintf ( stderr , " \n from %s \n to %s \n " , old_hex , new_hex ) ;
2009-10-31 08:47:30 +08:00
if ( dry_run ) {
if ( helper_status )
printf ( " ok %s \n " , ref - > name ) ;
2007-10-16 12:35:22 +08:00
continue ;
2009-10-31 08:47:30 +08:00
}
2005-11-03 03:19:24 +08:00
/* Lock remote branch ref */
2006-03-08 08:13:20 +08:00
ref_lock = lock_remote ( ref - > name , LOCK_TIME ) ;
if ( ref_lock = = NULL ) {
2005-11-03 03:19:24 +08:00
fprintf ( stderr , " Unable to lock remote branch %s \n " ,
2006-03-08 08:13:20 +08:00
ref - > name ) ;
2009-10-31 08:47:30 +08:00
if ( helper_status )
printf ( " error %s lock error \n " , ref - > name ) ;
2005-11-03 03:19:24 +08:00
rc = 1 ;
continue ;
}
2006-03-08 08:13:20 +08:00
/* Set up revision info for this refspec */
2006-03-22 07:49:05 +08:00
commit_argc = 3 ;
2006-09-02 12:16:31 +08:00
new_sha1_hex = xstrdup ( sha1_to_hex ( ref - > new_sha1 ) ) ;
2006-03-22 07:49:05 +08:00
old_sha1_hex = NULL ;
2006-03-11 12:17:55 +08:00
commit_argv [ 1 ] = " --objects " ;
commit_argv [ 2 ] = new_sha1_hex ;
2009-05-31 18:36:10 +08:00
if ( ! push_all & & ! is_null_sha1 ( ref - > old_sha1 ) ) {
2006-03-08 08:13:20 +08:00
old_sha1_hex = xmalloc ( 42 ) ;
sprintf ( old_sha1_hex , " ^%s " ,
sha1_to_hex ( ref - > old_sha1 ) ) ;
2006-03-11 12:17:55 +08:00
commit_argv [ 3 ] = old_sha1_hex ;
2006-03-08 08:13:20 +08:00
commit_argc + + ;
2005-11-03 03:19:24 +08:00
}
2009-05-21 17:32:44 +08:00
commit_argv [ commit_argc ] = NULL ;
2006-07-29 12:21:48 +08:00
init_revisions ( & revs , setup_git_directory ( ) ) ;
2006-03-08 08:13:20 +08:00
setup_revisions ( commit_argc , commit_argv , & revs , NULL ) ;
2008-06-08 02:39:20 +08:00
revs . edge_hint = 0 ; /* just in case */
2006-03-08 08:13:20 +08:00
free ( new_sha1_hex ) ;
if ( old_sha1_hex ) {
free ( old_sha1_hex ) ;
commit_argv [ 1 ] = NULL ;
2005-11-03 03:19:24 +08:00
}
2006-03-08 08:13:20 +08:00
/* Generate a list of objects that need to be pushed */
2005-11-03 03:19:24 +08:00
pushing = 0 ;
2008-02-18 15:31:56 +08:00
if ( prepare_revision_walk ( & revs ) )
die ( " revision walk setup failed " ) ;
2008-06-08 02:39:20 +08:00
mark_edges_uninteresting ( revs . commits , & revs , NULL ) ;
2006-03-11 12:18:33 +08:00
objects_to_send = get_delta ( & revs , ref_lock ) ;
2005-11-19 03:02:58 +08:00
finish_all_active_slots ( ) ;
2005-11-03 03:19:24 +08:00
/* Push missing objects to remote, this would be a
convenient time to pack them first if appropriate . */
pushing = 1 ;
2006-03-11 12:18:33 +08:00
if ( objects_to_send )
fprintf ( stderr , " sending %d objects \n " ,
objects_to_send ) ;
2009-06-06 16:43:27 +08:00
run_request_queue ( ) ;
2005-11-03 03:19:24 +08:00
/* Update the remote branch if all went well */
2008-02-15 07:26:12 +08:00
if ( aborted | | ! update_remote ( ref - > new_sha1 , ref_lock ) )
2006-03-08 08:13:20 +08:00
rc = 1 ;
2005-11-03 03:19:24 +08:00
2006-03-08 08:13:20 +08:00
if ( ! rc )
fprintf ( stderr , " done \n " ) ;
2009-10-31 08:47:30 +08:00
if ( helper_status )
printf ( " %s %s \n " , ! rc ? " ok " : " error " , ref - > name ) ;
2006-03-08 08:13:20 +08:00
unlock_remote ( ref_lock ) ;
2006-03-11 12:18:12 +08:00
check_locks ( ) ;
2005-11-03 03:19:24 +08:00
}
2006-03-11 12:18:18 +08:00
/* Update remote server info if appropriate */
2009-03-19 07:43:53 +08:00
if ( repo - > has_info_refs & & new_refs ) {
if ( info_ref_lock & & repo - > can_update_info_refs ) {
2006-03-11 12:18:18 +08:00
fprintf ( stderr , " Updating remote server info \n " ) ;
2007-10-16 12:35:22 +08:00
if ( ! dry_run )
update_remote_info_refs ( info_ref_lock ) ;
2006-03-11 12:18:18 +08:00
} else {
fprintf ( stderr , " Unable to update server info \n " ) ;
}
}
2005-11-03 03:19:24 +08:00
cleanup :
2008-01-19 23:22:47 +08:00
if ( info_ref_lock )
unlock_remote ( info_ref_lock ) ;
2009-03-19 07:43:53 +08:00
free ( repo ) ;
2005-11-03 03:19:24 +08:00
2005-11-19 03:02:58 +08:00
http_cleanup ( ) ;
2005-11-03 03:19:24 +08:00
request = request_queue_head ;
while ( request ! = NULL ) {
next_request = request - > next ;
release_request ( request ) ;
request = next_request ;
}
return rc ;
}