2 * changelist.c: implementation of the 'changelist' command
4 * ====================================================================
5 * Copyright (c) 2006-2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
19 /* ==================================================================== */
25 #include "svn_client.h"
27 #include "svn_pools.h"
32 #include "private/svn_wc_private.h"
35 /* Entry-walker callback for svn_client_add_to_changelist() and
36 svn_client_remove_from_changelist() below. */
37 struct set_cl_fe_baton
39 svn_wc_adm_access_t
*adm_access
;
40 const char *changelist
; /* NULL if removing changelists */
41 apr_hash_t
*changelist_hash
;
42 svn_client_ctx_t
*ctx
;
48 set_entry_changelist(const char *path
,
49 const svn_wc_entry_t
*entry
,
53 struct set_cl_fe_baton
*b
= (struct set_cl_fe_baton
*)baton
;
54 svn_wc_adm_access_t
*adm_access
;
56 /* We only care about files right now. */
57 if (entry
->kind
!= svn_node_file
)
59 if ((strcmp(SVN_WC_ENTRY_THIS_DIR
, entry
->name
) == 0)
60 && (b
->ctx
->notify_func2
))
61 b
->ctx
->notify_func2(b
->ctx
->notify_baton2
,
62 svn_wc_create_notify(path
,
69 /* See if this entry passes our changelist filtering. */
70 if (! SVN_WC__CL_MATCH(b
->changelist_hash
, entry
))
73 /* Get the ADM_ACCESS for our file's parent directory,
75 SVN_ERR(svn_wc_adm_retrieve(&adm_access
, b
->adm_access
,
76 svn_path_dirname(path
, pool
), pool
));
77 return svn_wc_set_changelist(path
, b
->changelist
, adm_access
,
78 b
->ctx
->cancel_func
, b
->ctx
->cancel_baton
,
79 b
->ctx
->notify_func2
, b
->ctx
->notify_baton2
,
84 static const svn_wc_entry_callbacks2_t set_cl_entry_callbacks
=
85 { set_entry_changelist
, svn_client__default_walker_error_handler
};
89 svn_client_add_to_changelist(const apr_array_header_t
*paths
,
90 const char *changelist
,
92 const apr_array_header_t
*changelists
,
93 svn_client_ctx_t
*ctx
,
96 /* ### Someday this routine might use a different underlying API to
97 ### to make the associations in a centralized database. */
99 apr_pool_t
*subpool
= svn_pool_create(pool
);
100 apr_hash_t
*changelist_hash
= NULL
;
103 if (changelists
&& changelists
->nelts
)
104 SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash
, changelists
, pool
));
106 for (i
= 0; i
< paths
->nelts
; i
++)
108 struct set_cl_fe_baton seb
;
109 svn_wc_adm_access_t
*adm_access
;
110 const char *path
= APR_ARRAY_IDX(paths
, i
, const char *);
112 svn_pool_clear(subpool
);
113 SVN_ERR(svn_wc_adm_probe_open3(&adm_access
, NULL
, path
,
114 TRUE
, /* write lock */ -1, /* infinity */
115 ctx
->cancel_func
, ctx
->cancel_baton
,
118 seb
.adm_access
= adm_access
;
119 seb
.changelist
= changelist
;
120 seb
.changelist_hash
= changelist_hash
;
123 SVN_ERR(svn_wc_walk_entries3(path
, adm_access
,
124 &set_cl_entry_callbacks
, &seb
,
125 depth
, FALSE
, /* no hidden entries */
126 ctx
->cancel_func
, ctx
->cancel_baton
,
129 SVN_ERR(svn_wc_adm_close(adm_access
));
132 svn_pool_destroy(subpool
);
138 svn_client_remove_from_changelists(const apr_array_header_t
*paths
,
140 const apr_array_header_t
*changelists
,
141 svn_client_ctx_t
*ctx
,
144 /* ### Someday this routine might use a different underlying API to
145 ### to make the associations in a centralized database. */
147 apr_pool_t
*subpool
= svn_pool_create(pool
);
148 apr_hash_t
*changelist_hash
= NULL
;
151 if (changelists
&& changelists
->nelts
)
152 SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash
, changelists
, pool
));
154 for (i
= 0; i
< paths
->nelts
; i
++)
156 struct set_cl_fe_baton seb
;
157 svn_wc_adm_access_t
*adm_access
;
158 const char *path
= APR_ARRAY_IDX(paths
, i
, const char *);
160 svn_pool_clear(subpool
);
161 SVN_ERR(svn_wc_adm_probe_open3(&adm_access
, NULL
, path
,
162 TRUE
, /* write lock */ -1, /* infinity */
163 ctx
->cancel_func
, ctx
->cancel_baton
,
166 seb
.adm_access
= adm_access
;
167 seb
.changelist
= NULL
;
168 seb
.changelist_hash
= changelist_hash
;
171 SVN_ERR(svn_wc_walk_entries3(path
, adm_access
,
172 &set_cl_entry_callbacks
, &seb
,
173 depth
, FALSE
, /* no hidden entries */
174 ctx
->cancel_func
, ctx
->cancel_baton
,
177 SVN_ERR(svn_wc_adm_close(adm_access
));
180 svn_pool_destroy(subpool
);
186 /* Entry-walker callback for svn_client_get_changelist() below. */
187 struct get_cl_fe_baton
189 svn_changelist_receiver_t callback_func
;
190 void *callback_baton
;
191 apr_hash_t
*changelists
;
197 get_entry_changelist(const char *path
,
198 const svn_wc_entry_t
*entry
,
202 struct get_cl_fe_baton
*b
= (struct get_cl_fe_baton
*)baton
;
204 /* If the entry has a changelist, and is a file or is the "this-dir"
205 entry for directory, and the changelist matches one that we're
206 looking for (or we aren't looking for any in particular)... */
207 if (SVN_WC__CL_MATCH(b
->changelists
, entry
)
208 && ((entry
->kind
== svn_node_file
)
209 || ((entry
->kind
== svn_node_dir
)
210 && (strcmp(entry
->name
, SVN_WC_ENTRY_THIS_DIR
) == 0))))
212 /* ...then call the callback function. */
213 SVN_ERR(b
->callback_func(b
->callback_baton
, path
,
214 entry
->changelist
, pool
));
221 static const svn_wc_entry_callbacks2_t get_cl_entry_callbacks
=
222 { get_entry_changelist
, svn_client__default_walker_error_handler
};
226 svn_client_get_changelists(const char *path
,
227 const apr_array_header_t
*changelists
,
229 svn_changelist_receiver_t callback_func
,
230 void *callback_baton
,
231 svn_client_ctx_t
*ctx
,
234 struct get_cl_fe_baton geb
;
235 svn_wc_adm_access_t
*adm_access
;
237 geb
.callback_func
= callback_func
;
238 geb
.callback_baton
= callback_baton
;
241 SVN_ERR(svn_hash_from_cstring_keys(&(geb
.changelists
), changelists
, pool
));
243 geb
.changelists
= NULL
;
244 SVN_ERR(svn_wc_adm_probe_open3(&adm_access
, NULL
, path
,
245 FALSE
, /* no write lock */
246 -1, /* levels to lock == infinity */
247 ctx
->cancel_func
, ctx
->cancel_baton
, pool
));
248 SVN_ERR(svn_wc_walk_entries3(path
, adm_access
, &get_cl_entry_callbacks
, &geb
,
249 depth
, FALSE
, /* don't show hidden entries */
250 ctx
->cancel_func
, ctx
->cancel_baton
, pool
));
251 SVN_ERR(svn_wc_adm_close(adm_access
));