Workaround Win32 problems with rename(2) applied to open/mapped files (it fails with EPERM). Thanks to Christopher Faylor for the hint regarding open files. The more complete patch. Signed-off-by: Alex Riesen diff --git a/apply.c b/apply.c --- a/apply.c +++ b/apply.c @@ -1453,9 +1453,12 @@ static int apply_patch(int fd) write_out_results(list, skipped_patch); if (write_index) { - if (write_cache(newfd, active_cache, active_nr) || - commit_index_file(&cache_file)) + if (write_cache(newfd, active_cache, active_nr)) die("Unable to write new cachefile"); + close(newfd); + unmap_active_cache(); + if (commit_index_file(&cache_file)) + die("Unable to commit new cachefile"); } if (show_files) diff --git a/cache.h b/cache.h --- a/cache.h +++ b/cache.h @@ -166,6 +166,7 @@ extern int ce_modified(struct cache_entr extern int ce_path_match(const struct cache_entry *ce, const char **pathspec); extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type); extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); +extern void unmap_active_cache(); struct cache_file { struct cache_file *next; diff --git a/checkout-index.c b/checkout-index.c --- a/checkout-index.c +++ b/checkout-index.c @@ -143,9 +143,13 @@ int main(int argc, char **argv) checkout_file(arg); } - if (0 <= newfd && - (write_cache(newfd, active_cache, active_nr) || - commit_index_file(&cache_file))) - die("Unable to write new cachefile"); + if (0 <= newfd) { + if (write_cache(newfd, active_cache, active_nr)) + die("Unable to write new cachefile"); + close(newfd); + unmap_active_cache(); + if (commit_index_file(&cache_file)) + die("Unable to commit new cachefile"); + } return 0; } diff --git a/read-cache.c b/read-cache.c --- a/read-cache.c +++ b/read-cache.c @@ -454,6 +454,17 @@ static int verify_hdr(struct cache_heade return 0; } +static void* active_cache_map = MAP_FAILED; +static size_t active_cache_map_size = 0; + +void unmap_active_cache() +{ + if ( active_cache_map != MAP_FAILED ) { + active_nr = 0; + munmap(active_cache_map, active_cache_map_size); + } +} + int read_cache(void) { int fd, i; @@ -490,6 +501,8 @@ int read_cache(void) if (verify_hdr(hdr, size) < 0) goto unmap; + active_cache_map = map; + active_cache_map_size = size; active_nr = ntohl(hdr->hdr_entries); active_alloc = alloc_nr(active_nr); active_cache = calloc(active_alloc, sizeof(struct cache_entry *)); diff --git a/read-tree.c b/read-tree.c --- a/read-tree.c +++ b/read-tree.c @@ -690,8 +690,11 @@ int main(int argc, char **argv) } unpack_trees(fn); - if (write_cache(newfd, active_cache, active_nr) || - commit_index_file(&cache_file)) + if (write_cache(newfd, active_cache, active_nr)) die("unable to write new index file"); + close(newfd); + unmap_active_cache(); + if (commit_index_file(&cache_file)) + die("unable to commit new index file"); return 0; } diff --git a/update-index.c b/update-index.c --- a/update-index.c +++ b/update-index.c @@ -392,9 +392,13 @@ int main(int argc, const char **argv) } } if (active_cache_changed) { - if (write_cache(newfd, active_cache, active_nr) || - commit_index_file(&cache_file)) + if (write_cache(newfd, active_cache, active_nr)) die("Unable to write new cachefile"); + /* close and unmap are just to workaround win32 stupidity */ + close(newfd); + unmap_active_cache(); + if (commit_index_file(&cache_file)) + die("Unable to commit new cachefile"); } return has_errors ? 1 : 0;