Merge with gitk.
[git.git] / local-pull.c
1 /*
2  * Copyright (C) 2005 Junio C Hamano
3  */
4 #include "cache.h"
5 #include "commit.h"
6 #include "pull.h"
7
8 static int use_link = 0;
9 static int use_symlink = 0;
10 static int use_filecopy = 1;
11
12 static char *path; /* "Remote" git repository */
13
14 void prefetch(unsigned char *sha1)
15 {
16 }
17
18 int fetch(unsigned char *sha1)
19 {
20         static int object_name_start = -1;
21         static char filename[PATH_MAX];
22         char *hex = sha1_to_hex(sha1);
23         const char *dest_filename = sha1_file_name(sha1);
24
25         if (object_name_start < 0) {
26                 strcpy(filename, path); /* e.g. git.git */
27                 strcat(filename, "/objects/");
28                 object_name_start = strlen(filename);
29         }
30         filename[object_name_start+0] = hex[0];
31         filename[object_name_start+1] = hex[1];
32         filename[object_name_start+2] = '/';
33         strcpy(filename + object_name_start + 3, hex + 2);
34         if (use_link) {
35                 if (!link(filename, dest_filename)) {
36                         pull_say("link %s\n", hex);
37                         return 0;
38                 }
39                 /* If we got ENOENT there is no point continuing. */
40                 if (errno == ENOENT) {
41                         fprintf(stderr, "does not exist %s\n", filename);
42                         return -1;
43                 }
44         }
45         if (use_symlink && !symlink(filename, dest_filename)) {
46                 pull_say("symlink %s\n", hex);
47                 return 0;
48         }
49         if (use_filecopy) {
50                 int ifd, ofd, status;
51                 struct stat st;
52                 void *map;
53                 ifd = open(filename, O_RDONLY);
54                 if (ifd < 0 || fstat(ifd, &st) < 0) {
55                         close(ifd);
56                         fprintf(stderr, "cannot open %s\n", filename);
57                         return -1;
58                 }
59                 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, ifd, 0);
60                 close(ifd);
61                 if (map == MAP_FAILED) {
62                         fprintf(stderr, "cannot mmap %s\n", filename);
63                         return -1;
64                 }
65                 ofd = open(dest_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
66                 status = ((ofd < 0) ||
67                           (write(ofd, map, st.st_size) != st.st_size));
68                 munmap(map, st.st_size);
69                 close(ofd);
70                 if (status)
71                         fprintf(stderr, "cannot write %s\n", dest_filename);
72                 else
73                         pull_say("copy %s\n", hex);
74                 return status;
75         }
76         fprintf(stderr, "failed to copy %s with given copy methods.\n", hex);
77         return -1;
78 }
79
80 int fetch_ref(char *ref, unsigned char *sha1)
81 {
82         static int ref_name_start = -1;
83         static char filename[PATH_MAX];
84         static char hex[41];
85         int ifd;
86
87         if (ref_name_start < 0) {
88                 sprintf(filename, "%s/refs/", path);
89                 ref_name_start = strlen(filename);
90         }
91         strcpy(filename + ref_name_start, ref);
92         ifd = open(filename, O_RDONLY);
93         if (ifd < 0) {
94                 close(ifd);
95                 fprintf(stderr, "cannot open %s\n", filename);
96                 return -1;
97         }
98         if (read(ifd, hex, 40) != 40 || get_sha1_hex(hex, sha1)) {
99                 close(ifd);
100                 fprintf(stderr, "cannot read from %s\n", filename);
101                 return -1;
102         }
103         close(ifd);
104         pull_say("ref %s\n", sha1_to_hex(sha1));
105         return 0;
106 }
107
108 static const char local_pull_usage[] =
109 "git-local-pull [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path";
110
111 /* 
112  * By default we only use file copy.
113  * If -l is specified, a hard link is attempted.
114  * If -s is specified, then a symlink is attempted.
115  * If -n is _not_ specified, then a regular file-to-file copy is done.
116  */
117 int main(int argc, char **argv)
118 {
119         char *commit_id;
120         int arg = 1;
121
122         while (arg < argc && argv[arg][0] == '-') {
123                 if (argv[arg][1] == 't')
124                         get_tree = 1;
125                 else if (argv[arg][1] == 'c')
126                         get_history = 1;
127                 else if (argv[arg][1] == 'a') {
128                         get_all = 1;
129                         get_tree = 1;
130                         get_history = 1;
131                 }
132                 else if (argv[arg][1] == 'l')
133                         use_link = 1;
134                 else if (argv[arg][1] == 's')
135                         use_symlink = 1;
136                 else if (argv[arg][1] == 'n')
137                         use_filecopy = 0;
138                 else if (argv[arg][1] == 'v')
139                         get_verbosely = 1;
140                 else if (argv[arg][1] == 'w')
141                         write_ref = argv[++arg];
142                 else
143                         usage(local_pull_usage);
144                 arg++;
145         }
146         if (argc < arg + 2)
147                 usage(local_pull_usage);
148         commit_id = argv[arg];
149         path = argv[arg + 1];
150
151         if (pull(commit_id))
152                 return 1;
153
154         return 0;
155 }