Re: [Rory Yorke] Re: Unexpected temporary directory
Yasuhiro MATSUMOTO <[email protected]> Thu, 6 Mar 2014 14:23:50 +0900
| Newsgroups | gmane.comp.ipod.gtkpod |
|---|---|
| Message-ID | <CAJc+XFMoLTrRLY2GZ-i5KnkW=tru87zJm85NDvxDL2m=nqB2eg@mail.gmail.com> |
--===============3555357946737899055==
Content-Type: multipart/alternative; boundary=089e0149d2f6b0b92d04f3e95751
--089e0149d2f6b0b92d04f3e95751
Content-Type: text/plain; charset=UTF-8
> How about this instead?
>
> diff --git a/src/itdb_sqlite.c b/src/itdb_sqlite.c
> index b5b2975..23c645f 100644
> --- a/src/itdb_sqlite.c
> +++ b/src/itdb_sqlite.c
> @@ -2278,8 +2278,9 @@ int itdb_sqlite_generate_itdbs(FExport *fexp)
>
> tzoffset = fexp->itdb->tzoffset;
>
> - tmpdir = g_build_path(g_get_tmp_dir(), tmpnam(NULL), NULL);
> - if (g_mkdir(tmpdir, 0755) != 0) {
> + tmpdir = g_build_path(G_DIR_SEPARATOR_S, g_get_tmp_dir(),
"libgpod.XXXXXX", NULL);
> +
> + if (!g_mkdtemp(tmpdir)) {
> g_set_error (&fexp->error, G_FILE_ERROR, g_file_error_from_errno(errno),
> "Could not create temporary directory '%s': %s",
> tmpdir, strerror(errno));
>
> mkstemp() creates a temporary file and returns its file-handle,
> according to
> https://developer.gnome.org/glib/2.37/glib-File-Utilities.html#g-mkstemp
> (and, I think, in common with typical mkstemp() implementations). Your
> patch caused libgpod.BLAH files to be created in the CWD, as well as
> /tmp/libgpod.BLAH to be created.
>
> It looks like mkdtemp() is what we want, though I see there's a
> g_dir_make_tmp() too.
>
> I don't know if this will work on Windows, but I imagine it should.
Docs says:
"the template should only be a basename, no directory components are
allowed"
So patch should be https://gist.github.com/mattn/9383016
But on windows, g_dir_make_tmp() is tool newer API. So I can't build it.
And g_array_set_clear_func() is also newer APIs for windows.
Currently, glib for windows is version 2.28.8 . I hope to revert with
below's patch.
Thanks.
- Yasuhiro Matsumoto
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index a177e26..7fe178e 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -1155,7 +1155,7 @@ static gboolean playcounts_plist_read (FImport *fimp,
GValue *plist_data)
struct playcount *playcount;
GHashTable *pc_dict, *track_dict;
GValue *to_parse;
- GArray *array;
+ GValueArray *array;
gint i;
guint32 mac_time;
guint64 *dbid;
@@ -1167,19 +1167,19 @@ static gboolean playcounts_plist_read (FImport
*fimp, GValue *plist_data)
if (to_parse == NULL) {
return FALSE;
}
- if (!G_VALUE_HOLDS (to_parse, G_TYPE_ARRAY)) {
+ if (!G_VALUE_HOLDS (to_parse, G_TYPE_VALUE_ARRAY)) {
return FALSE;
}
playcounts = g_hash_table_new_full (g_int64_hash, g_int64_equal,
g_free, g_free);
- array = (GArray*)g_value_get_boxed (to_parse);
- for (i = 0; i < array->len; i++) {
- if (!G_VALUE_HOLDS (g_array_index (array, GValue *, i),
G_TYPE_HASH_TABLE)) {
+ array = (GValueArray*)g_value_get_boxed (to_parse);
+ for (i = 0; i < array->n_values; i++) {
+ if (!G_VALUE_HOLDS (g_value_array_get_nth (array, i),
G_TYPE_HASH_TABLE)) {
continue;
}
- track_dict = g_value_get_boxed (g_array_index (array, GValue *, i));
+ track_dict = g_value_get_boxed (g_value_array_get_nth (array, i));
if (track_dict == NULL)
continue;
diff --git a/src/itdb_plist.c b/src/itdb_plist.c
index 4104cb8..b0cfbf1 100644
--- a/src/itdb_plist.c
+++ b/src/itdb_plist.c
@@ -40,7 +40,7 @@
* - <integer> => G_TYPE_INT64 (gint64)
* - <true/>, <false/> => G_TYPE_BOOLEAN (gboolean)
* - <data> => G_TYPE_GSTRING (GString *)
- * - <array> => G_TYPE_ARRAY (GArray *)
+ * - <array> => G_TYPE_VALUE_ARRAY (GValueArray *)
* - <dict> => G_TYPE_HASH_TABLE (GHashTable *)
*/
#ifdef HAVE_CONFIG_H
@@ -70,6 +70,7 @@ extern GQuark itdb_device_error_quark (void);
static GValue *parse_node (xmlNode *a_node, GError **error);
+
static void
value_free (GValue *val)
{
@@ -275,17 +276,17 @@ parse_array (xmlNode *a_node, GError **error)
{
xmlNode *cur_node = a_node->children;
GValue *value;
- GArray *array;
+ GValueArray *array;
- array = g_array_new (FALSE, TRUE, sizeof(GValue));
- g_array_set_clear_func (array, (GDestroyNotify)g_value_unset);
+ array = g_value_array_new (4);
while (cur_node != NULL) {
if (get_parser_for_type (cur_node->name) != NULL) {
GValue *cur_value;
cur_value = parse_node (cur_node, error);
if (cur_value != NULL) {
- array = g_array_append_vals (array, cur_value, 1);
+ array = g_value_array_append (array, cur_value);
+ g_value_unset (cur_value);
g_free (cur_value);
}
}
@@ -298,11 +299,11 @@ parse_array (xmlNode *a_node, GError **error)
}
if ((error != NULL) && (*error != NULL)) {
- g_array_unref (array);
+ g_value_array_free (array);
return NULL;
}
value = g_new0 (GValue, 1);
- value = g_value_init (value, G_TYPE_ARRAY);
+ value = g_value_init (value, G_TYPE_VALUE_ARRAY);
g_value_take_boxed (value, array);
return value;
diff --git a/src/itdb_sysinfo_extended_parser.c
b/src/itdb_sysinfo_extended_parser.c
index 78dcf70..cc09c49 100644
--- a/src/itdb_sysinfo_extended_parser.c
+++ b/src/itdb_sysinfo_extended_parser.c
@@ -479,26 +479,26 @@ static GList *parse_one_formats_list (GHashTable
*sysinfo_dict,
{
GValue *to_parse;
GList *formats = NULL;
- GArray *array;
+ GValueArray *array;
gint i;
to_parse = g_hash_table_lookup (sysinfo_dict, key);
if (to_parse == NULL) {
return NULL;
}
- if (!G_VALUE_HOLDS (to_parse, G_TYPE_ARRAY)) {
+ if (!G_VALUE_HOLDS (to_parse, G_TYPE_VALUE_ARRAY)) {
return NULL;
}
- array = (GArray*)g_value_get_boxed (to_parse);
- for (i = 0; i < array->len; i++) {
+ array = (GValueArray*)g_value_get_boxed (to_parse);
+ for (i = 0; i < array->n_values; i++) {
Itdb_ArtworkFormat *format;
/* SysInfoExtended on the iPhone has <string> fields in the artwork
* format array in addition to the hash we parse
*/
- if (!G_VALUE_HOLDS (&g_array_index (array, GValue, i),
G_TYPE_HASH_TABLE)) {
+ if (!G_VALUE_HOLDS (g_value_array_get_nth (array, i), G_TYPE_HASH_TABLE))
{
continue;
}
- format = g_value_to_image_format (&g_array_index (array, GValue, i));
+ format = g_value_to_image_format (g_value_array_get_nth (array, i));
if (format != NULL) {
formats = g_list_prepend (formats, format);
}
--089e0149d2f6b0b92d04f3e95751
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div><div>> How about this i=
nstead?</div><div>>=C2=A0</div><div>> diff --git a/src/itdb_sqlite.c =
b/src/itdb_sqlite.c</div><div>> index b5b2975..23c645f 100644</div><div>=
> --- a/src/itdb_sqlite.c</div>
<div>> +++ b/src/itdb_sqlite.c</div><div>> @@ -2278,8 +2278,9 @@ int =
itdb_sqlite_generate_itdbs(FExport *fexp)</div><div>> =C2=A0</div><div>&=
gt; =C2=A0 =C2=A0 =C2=A0tzoffset =3D fexp->itdb->tzoffset;</div><div>=
> =C2=A0</div><div>> - =C2=A0 =C2=A0tmpdir =3D g_build_path(g_get_tmp=
_dir(), tmpnam(NULL), NULL);</div>
<div>> - =C2=A0 =C2=A0if (g_mkdir(tmpdir, 0755) !=3D 0) {</div><div>>=
+ =C2=A0 =C2=A0tmpdir =3D g_build_path(G_DIR_SEPARATOR_S, g_get_tmp_dir(),=
"libgpod.XXXXXX", NULL);</div><div>> +</div><div>> + =C2=
=A0 =C2=A0if (!g_mkdtemp(tmpdir)) {</div>
<div>> =C2=A0<span class=3D"" style=3D"white-space:pre"> </span>g_set_er=
ror (&fexp->error, G_FILE_ERROR, g_file_error_from_errno(errno),</di=
v><div>> =C2=A0<span class=3D"" style=3D"white-space:pre"> </span> =C2=
=A0 =C2=A0 "Could not create temporary directory '%s': %s"=
;,</div>
<div>> =C2=A0<span class=3D"" style=3D"white-space:pre"> </span> =C2=A0=
=C2=A0 tmpdir, strerror(errno));</div><div>>=C2=A0</div><div>> mkste=
mp() creates a temporary file and returns its file-handle,</div><div>> a=
ccording to</div><div>
> <a href=3D"https://developer.gnome.org/glib/2.37/glib-File-Utilities.h=
tml#g-mkstemp">https://developer.gnome.org/glib/2.37/glib-File-Utilities.ht=
ml#g-mkstemp</a></div><div>> (and, I think, in common with typical mkste=
mp() implementations). =C2=A0Your</div>
<div>> patch caused libgpod.BLAH files to be created in the CWD, as well=
as</div><div>> /tmp/libgpod.BLAH to be created.</div><div>>=C2=A0</d=
iv><div>> It looks like mkdtemp() is what we want, though I see there=
9;s a</div>
<div>> g_dir_make_tmp() too.</div><div>>=C2=A0</div><div>> I don&#=
39;t know if this will work on Windows, but I imagine it should.</div><div>=
<br></div><div>Docs says:</div><div>"the template should only be a bas=
ename, no directory components are allowed"</div>
<div><br></div><div>So patch should be <a href=3D"https://gist.github.com/m=
attn/9383016">https://gist.github.com/mattn/9383016</a></div><div><br></div=
><div>But on windows, g_dir_make_tmp() is tool newer API. So I can't bu=
ild it.</div>
<div>And g_array_set_clear_func() is also newer APIs for windows.</div><div=
>Currently, glib for windows is version 2.28.8 . I hope to revert with</div=
><div>below's patch.</div><div><br></div><div>Thanks.</div><div>- Yasuh=
iro Matsumoto</div>
<div><br></div><div>diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c<=
/div><div>index a177e26..7fe178e 100644</div><div>--- a/src/itdb_itunesdb.c=
</div><div>+++ b/src/itdb_itunesdb.c</div><div>@@ -1155,7 +1155,7 @@ static=
gboolean playcounts_plist_read (FImport *fimp, GValue *plist_data)</div>
<div>=C2=A0 =C2=A0 =C2=A0struct playcount *playcount;</div><div>=C2=A0 =C2=
=A0 =C2=A0GHashTable *pc_dict, *track_dict;</div><div>=C2=A0 =C2=A0 =C2=A0G=
Value *to_parse;</div><div>- =C2=A0 =C2=A0GArray *array;</div><div>+ =C2=A0=
=C2=A0GValueArray *array;</div><div>=C2=A0 =C2=A0 =C2=A0gint i;</div><div>=
=C2=A0 =C2=A0 =C2=A0guint32 mac_time;</div>
<div>=C2=A0 =C2=A0 =C2=A0guint64 *dbid;</div><div>@@ -1167,19 +1167,19 @@ s=
tatic gboolean playcounts_plist_read (FImport *fimp, GValue *plist_data)</d=
iv><div>=C2=A0 =C2=A0 =C2=A0if (to_parse =3D=3D NULL) {</div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0return FALSE;</div><div>=C2=A0 =C2=A0 =C2=A0}</d=
iv>
<div>- =C2=A0 =C2=A0if (!G_VALUE_HOLDS (to_parse, G_TYPE_ARRAY)) {</div><di=
v>+ =C2=A0 =C2=A0if (!G_VALUE_HOLDS (to_parse, G_TYPE_VALUE_ARRAY)) {</div>=
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return FALSE;</div><div>=C2=A0 =C2=
=A0 =C2=A0}</div><div>=C2=A0</div><div>=C2=A0 =C2=A0 =C2=A0playcounts =3D g=
_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, g_free);</div>
<div>=C2=A0</div><div>- =C2=A0 =C2=A0array =3D (GArray*)g_value_get_boxed (=
to_parse);</div><div>- =C2=A0 =C2=A0for (i =3D 0; i < array->len; i++=
) {</div><div>- =C2=A0 =C2=A0 =C2=A0 if (!G_VALUE_HOLDS (g_array_index (arr=
ay, GValue *, i), G_TYPE_HASH_TABLE)) {</div>
<div>+ =C2=A0 =C2=A0array =3D (GValueArray*)g_value_get_boxed (to_parse);</=
div><div>+ =C2=A0 =C2=A0for (i =3D 0; i < array->n_values; i++) {</di=
v><div>+ =C2=A0 =C2=A0 =C2=A0 if (!G_VALUE_HOLDS (g_value_array_get_nth (ar=
ray, i), G_TYPE_HASH_TABLE)) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0continue;</div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 }</div><div>=C2=A0</div><div>- =C2=A0 =C2=A0 =C2=A0 tr=
ack_dict =3D g_value_get_boxed (g_array_index (array, GValue *, i));</div><=
div>+ =C2=A0 =C2=A0 =C2=A0 track_dict =3D g_value_get_boxed (g_value_array_=
get_nth (array, i));</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (track_dict =3D=3D NULL)</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;</div><div>=C2=A0</div><div=
>diff --git a/src/itdb_plist.c b/src/itdb_plist.c</div><div>index 4104cb8..=
b0cfbf1 100644</div><div>--- a/src/itdb_plist.c</div><div>
+++ b/src/itdb_plist.c</div><div>@@ -40,7 +40,7 @@</div><div>=C2=A0 * =C2=
=A0 =C2=A0 =C2=A0- <integer> =3D> G_TYPE_INT64 (gint64)</div><div>=
=C2=A0 * =C2=A0 =C2=A0 =C2=A0- <true/>, <false/> =3D> G_TYPE=
_BOOLEAN (gboolean)</div><div>=C2=A0 * =C2=A0 =C2=A0 =C2=A0- <data> =
=3D> G_TYPE_GSTRING (GString *)</div>
<div>- * =C2=A0 =C2=A0 =C2=A0- <array> =3D> G_TYPE_ARRAY (GArray *=
)</div><div>+ * =C2=A0 =C2=A0 =C2=A0- <array> =3D> G_TYPE_VALUE_AR=
RAY (GValueArray *)</div><div>=C2=A0 * =C2=A0 =C2=A0 =C2=A0- <dict> =
=3D> G_TYPE_HASH_TABLE (GHashTable *)</div><div>=C2=A0 */</div>
<div>=C2=A0#ifdef HAVE_CONFIG_H</div><div>@@ -70,6 +70,7 @@ extern GQuark i=
tdb_device_error_quark (void);</div><div>=C2=A0</div><div>=C2=A0static GVal=
ue *parse_node (xmlNode *a_node, GError **error);</div><div>=C2=A0</div><di=
v>+</div><div>=C2=A0static void</div>
<div>=C2=A0value_free (GValue *val)</div><div>=C2=A0{</div><div>@@ -275,17 =
+276,17 @@ parse_array (xmlNode *a_node, GError **error)</div><div>=C2=A0{<=
/div><div>=C2=A0 =C2=A0 =C2=A0xmlNode *cur_node =3D a_node->children;</d=
iv><div>=C2=A0 =C2=A0 =C2=A0GValue *value;</div>
<div>- =C2=A0 =C2=A0GArray *array;</div><div>+ =C2=A0 =C2=A0GValueArray *ar=
ray;</div><div>=C2=A0</div><div>- =C2=A0 =C2=A0array =3D g_array_new (FALSE=
, TRUE, sizeof(GValue));</div><div>- =C2=A0 =C2=A0g_array_set_clear_func (a=
rray, (GDestroyNotify)g_value_unset);</div>
<div>+ =C2=A0 =C2=A0array =3D g_value_array_new (4);</div><div>=C2=A0</div>=
<div>=C2=A0 =C2=A0 =C2=A0while (cur_node !=3D NULL) {</div><div>=C2=A0<span=
class=3D"" style=3D"white-space:pre"> </span>if (get_parser_for_type (cur_=
node->name) !=3D NULL) {</div><div>=C2=A0<span class=3D"" style=3D"white=
-space:pre"> </span> =C2=A0 =C2=A0GValue *cur_value;</div>
<div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span> =C2=A0 =C2=
=A0cur_value =3D parse_node (cur_node, error);</div><div>=C2=A0<span class=
=3D"" style=3D"white-space:pre"> </span> =C2=A0 =C2=A0if (cur_value !=3D NU=
LL) {</div><div>-<span class=3D"" style=3D"white-space:pre"> </span>array =
=3D g_array_append_vals (array, cur_value, 1);</div>
<div>+<span class=3D"" style=3D"white-space:pre"> </span>array =3D g_value=
_array_append (array, cur_value);</div><div>+<span class=3D"" style=3D"whit=
e-space:pre"> </span>g_value_unset (cur_value);</div><div>=C2=A0<span clas=
s=3D"" style=3D"white-space:pre"> </span>g_free (cur_value);</div>
<div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span> =C2=A0 =C2=
=A0}</div><div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span>}</=
div><div>@@ -298,11 +299,11 @@ parse_array (xmlNode *a_node, GError **error=
)</div><div>=C2=A0 =C2=A0 =C2=A0}</div><div>
=C2=A0</div><div>=C2=A0 =C2=A0 =C2=A0if ((error !=3D NULL) && (*err=
or !=3D NULL)) {</div><div>-<span class=3D"" style=3D"white-space:pre"> </s=
pan>g_array_unref (array);</div><div>+<span class=3D"" style=3D"white-space=
:pre"> </span>g_value_array_free (array);</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;</div><div>=C2=A0 =C2=A0=
=C2=A0}</div><div>=C2=A0 =C2=A0 =C2=A0value =3D g_new0 (GValue, 1);</div><=
div>- =C2=A0 =C2=A0value =3D g_value_init (value, G_TYPE_ARRAY);</div><div>=
+ =C2=A0 =C2=A0value =3D g_value_init (value, G_TYPE_VALUE_ARRAY);</div><di=
v>
=C2=A0 =C2=A0 =C2=A0g_value_take_boxed (value, array);</div><div>=C2=A0</di=
v><div>=C2=A0 =C2=A0 =C2=A0return value;</div><div>diff --git a/src/itdb_sy=
sinfo_extended_parser.c b/src/itdb_sysinfo_extended_parser.c</div><div>inde=
x 78dcf70..cc09c49 100644</div>
<div>--- a/src/itdb_sysinfo_extended_parser.c</div><div>+++ b/src/itdb_sysi=
nfo_extended_parser.c</div><div>@@ -479,26 +479,26 @@ static GList *parse_o=
ne_formats_list (GHashTable *sysinfo_dict,</div><div>=C2=A0{</div><div>=C2=
=A0 =C2=A0 =C2=A0GValue *to_parse;</div>
<div>=C2=A0 =C2=A0 =C2=A0GList *formats =3D NULL;</div><div>- =C2=A0 =C2=A0=
GArray *array;</div><div>+ =C2=A0 =C2=A0GValueArray *array;</div><div>=C2=
=A0 =C2=A0 =C2=A0gint i;</div><div>=C2=A0</div><div>=C2=A0 =C2=A0 =C2=A0to_=
parse =3D g_hash_table_lookup (sysinfo_dict, key);</div><div>=C2=A0 =C2=A0 =
=C2=A0if (to_parse =3D=3D NULL) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;</div><div>=C2=A0 =C2=A0=
=C2=A0}</div><div>- =C2=A0 =C2=A0if (!G_VALUE_HOLDS (to_parse, G_TYPE_ARRA=
Y)) {</div><div>+ =C2=A0 =C2=A0if (!G_VALUE_HOLDS (to_parse, G_TYPE_VALUE_A=
RRAY)) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;</div><div=
>=C2=A0 =C2=A0 =C2=A0}</div>
<div>- =C2=A0 =C2=A0array =3D (GArray*)g_value_get_boxed (to_parse);</div><=
div>- =C2=A0 =C2=A0for (i =3D 0; i < array->len; i++) {</div><div>+ =
=C2=A0 =C2=A0array =3D (GValueArray*)g_value_get_boxed (to_parse);</div><di=
v>+ =C2=A0 =C2=A0for (i =3D 0; i < array->n_values; i++) {</div>
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Itdb_ArtworkFormat *format;</div><di=
v>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span>/* SysInfoExtend=
ed on the iPhone has <string> fields in the artwork</div><div>=C2=A0<=
span class=3D"" style=3D"white-space:pre"> </span> * format array in additi=
on to the hash we parse</div>
<div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span> */</div><div=
>-<span class=3D"" style=3D"white-space:pre"> </span>if (!G_VALUE_HOLDS (&a=
mp;g_array_index (array, GValue, i), G_TYPE_HASH_TABLE)) {</div><div>+<span=
class=3D"" style=3D"white-space:pre"> </span>if (!G_VALUE_HOLDS (g_value_a=
rray_get_nth (array, i), G_TYPE_HASH_TABLE)) {</div>
<div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span> =C2=A0 =C2=
=A0continue;</div><div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </=
span>}</div><div>-<span class=3D"" style=3D"white-space:pre"> </span>format=
=3D g_value_to_image_format (&g_array_index (array, GValue, i));</div>
<div>+<span class=3D"" style=3D"white-space:pre"> </span>format =3D g_value=
_to_image_format (g_value_array_get_nth (array, i));</div><div>=C2=A0<span =
class=3D"" style=3D"white-space:pre"> </span>if (format !=3D NULL) {</div><=
div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span>formats =3D g=
_list_prepend (formats, format);</div>
<div>=C2=A0<span class=3D"" style=3D"white-space:pre"> </span>}</div><div><=
br></div></div>
</div></div>
--089e0149d2f6b0b92d04f3e95751--
--===============3555357946737899055==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
------------------------------------------------------------------------------
Subversion Kills Productivity. Get off Subversion & Make the Move to Perforce.
With Perforce, you get hassle-free workflows. Merge that actually works.
Faster operations. Version large binaries. Built-in WAN optimization and the
freedom to use Git, Perforce or both. Make the move to Perforce.
http://pubads.g.doubleclick.net/gampad/clk?id=122218951&iu=/4140/ostg.clktrk
--===============3555357946737899055==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Gtkpod-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-devel
--===============3555357946737899055==--