1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-24 08:43:27 +00:00

(libT) #1220 'change top folder names' -- when the root file/folder is changed, update tr_info.name too.

This commit is contained in:
Jordan Lee 2013-01-22 00:25:42 +00:00
parent 9236571f1c
commit 434bd6b287
8 changed files with 150 additions and 13 deletions

View file

@ -36,8 +36,9 @@ char*
tr_metainfoGetBasename (const tr_info * inf)
{
size_t i;
const size_t name_len = strlen (inf->name);
char * ret = tr_strdup_printf ("%s.%16.16s", inf->name, inf->hashString);
const char * name = inf->originalName;
const size_t name_len = strlen (name);
char * ret = tr_strdup_printf ("%s.%16.16s", name, inf->hashString);
for (i=0; i<name_len; ++i)
if (ret[i] == '/')
@ -405,11 +406,15 @@ tr_metainfoParseImpl (const tr_session * session,
if (tr_variantDictFindStr (d, TR_KEY_display_name, &str, &len))
{
tr_free (inf->name);
tr_free (inf->originalName);
inf->name = tr_strndup (str, len);
inf->originalName = tr_strndup (str, len);
}
if (!inf->name)
inf->name = tr_strdup (inf->hashString);
inf->name = tr_strdup (inf->hashString);
if (!inf->originalName)
inf->originalName = tr_strdup (inf->hashString);
}
else /* not a magnet link and has no info dict... */
{
@ -439,7 +444,9 @@ tr_metainfoParseImpl (const tr_session * session,
if (!str || !*str)
return "name";
tr_free (inf->name);
tr_free (inf->originalName);
inf->name = tr_utf8clean (str, len);
inf->originalName = tr_strdup (inf->name);
}
/* comment */
@ -560,6 +567,7 @@ tr_metainfoFree (tr_info * inf)
tr_free (inf->comment);
tr_free (inf->creator);
tr_free (inf->torrent);
tr_free (inf->originalName);
tr_free (inf->name);
for (i=0; i<inf->trackerCount; i++)

View file

@ -154,6 +154,7 @@ create_torrent_from_base64_metainfo (tr_ctor * ctor, const char * metainfo_base6
static int
test_single_filename_torrent (void)
{
uint64_t loaded;
tr_torrent * tor;
char * tmpstr;
const size_t totalSize = 14;
@ -207,12 +208,22 @@ test_single_filename_torrent (void)
tmpstr = tr_buildPath (tor->downloadDir, "hello-world.txt", NULL);
check (tr_fileExists (tmpstr, NULL));
check_streq ("hello-world.txt", tr_torrentName(tor));
check_int_eq (0, torrentRenameAndWait (tor, "hello-world.txt", "foobar"));
check (!tr_fileExists (tmpstr, NULL));
check (tor->info.files[0].is_renamed);
check_streq ("foobar", tor->info.files[0].name);
tr_free (tmpstr);
check_streq ("foobar", tr_torrentName(tor));
check (strstr (tor->info.torrent, "foobar") == NULL);
check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n"));
tr_free (tmpstr);
/* (while it's renamed: confirm that the .resume file remembers the changes) */
tr_torrentSaveResume (tor);
sync ();
loaded = tr_torrentLoadResume (tor, ~0, ctor);
check_streq ("foobar", tr_torrentName(tor));
check ((loaded & TR_FR_NAME) != 0);
/***
**** ...and rename it back again
@ -224,6 +235,7 @@ test_single_filename_torrent (void)
check (!tr_fileExists (tmpstr, NULL));
check (tor->info.files[0].is_renamed);
check_streq ("hello-world.txt", tor->info.files[0].name);
check_streq ("hello-world.txt", tr_torrentName(tor));
tr_free (tmpstr);
check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n"));
@ -265,12 +277,9 @@ create_multifile_torrent_contents (const char * top)
static int
test_multifile_torrent (void)
{
//tr_file_stat * file_stats;
//tr_file_index_t n;
tr_file_index_t i;
uint64_t loaded;
tr_torrent * tor;
//tr_file_index_t i;
tr_ctor * ctor;
char * str;
char * tmp;

View file

@ -340,6 +340,36 @@ loadIdleLimits (tr_variant * dict, tr_torrent * tor)
****
***/
static void
saveName (tr_variant * dict, const tr_torrent * tor)
{
tr_variantDictAddStr (dict, TR_KEY_name, tr_torrentName(tor));
}
static uint64_t
loadName (tr_variant * dict, tr_torrent * tor)
{
uint64_t ret = 0;
const char * name;
if (tr_variantDictFindStr (dict, TR_KEY_name, &name, NULL))
{
ret = TR_FR_NAME;
if (tr_strcmp0 (tr_torrentName(tor), name))
{
tr_free (tor->info.name);
tor->info.name = tr_strdup (name);
}
}
return ret;
}
/***
****
***/
static void
saveFilenames (tr_variant * dict, const tr_torrent * tor)
{
@ -650,6 +680,7 @@ tr_torrentSaveResume (tr_torrent * tor)
saveRatioLimits (&top, tor);
saveIdleLimits (&top, tor);
saveFilenames (&top, tor);
saveName (&top, tor);
filename = getResumeFilename (tor);
if ((err = tr_variantToFile (&top, TR_VARIANT_FMT_BENC, filename)))
@ -805,6 +836,9 @@ loadFromFile (tr_torrent * tor, uint64_t fieldsToLoad)
if (fieldsToLoad & TR_FR_FILENAMES)
fieldsLoaded |= loadFilenames (&top, tor);
if (fieldsToLoad & TR_FR_NAME)
fieldsLoaded |= loadName (&top, tor);
/* loading the resume file triggers of a lot of changes,
* but none of them needs to trigger a re-saving of the
* same resume information... */

View file

@ -39,7 +39,8 @@ enum
TR_FR_IDLELIMIT = (1 << 17),
TR_FR_TIME_SEEDING = (1 << 18),
TR_FR_TIME_DOWNLOADING = (1 << 19),
TR_FR_FILENAMES = (1 << 20)
TR_FR_FILENAMES = (1 << 20),
TR_FR_NAME = (1 << 21),
};
/**
@ -53,4 +54,7 @@ void tr_torrentSaveResume (tr_torrent * tor);
void tr_torrentRemoveResume (const tr_torrent * tor);
int tr_torrentRenameResume (const tr_torrent * tor,
const char * newname);
#endif

View file

@ -374,6 +374,7 @@ tr_torrentGetMetadataPercent (const tr_torrent * tor)
return ret;
}
/* FIXME: this should be renamed tr_metainfoGetMagnetLink() and moved to metainfo.c for consistency */
char *
tr_torrentInfoGetMagnetLink (const tr_info * inf)
{

View file

@ -3440,6 +3440,16 @@ struct rename_data
void * callback_user_data;
};
static void
torrentRenameDone (tr_torrent * tor UNUSED,
const char * oldpath UNUSED,
const char * newname UNUSED,
int error,
void * user_data)
{
*(int*)user_data = error;
}
static void
torrentRenamePath (void * vdata)
{
@ -3477,8 +3487,14 @@ torrentRenamePath (void * vdata)
if (!error)
{
/* update tr_info.files */
for (i=0; i<n; ++i)
renameTorrentFileString(tor, oldpath, newname, file_indices[i]);
/* update tr_info.name if user changed the toplevel */
if ((n == tor->info.fileCount) && (strchr(oldpath,'/')==NULL))
tr_torrentRename (tor, newname, torrentRenameDone, &error);
tr_torrentSetDirty (tor);
}
}
@ -3521,3 +3537,44 @@ tr_torrentRenamePath (tr_torrent * tor,
tr_runInEventThread (tor->session, torrentRenamePath, data);
}
/**
***
**/
static void
torrentRename (void * vdata)
{
int error = 0;
struct rename_data * data = vdata;
tr_torrent * const tor = data->tor;
tr_free (tor->info.name);
tor->info.name = data->newname;
tr_torrentSetDirty (tor);
tor->anyDate = tr_time ();
/* callback */
if (data->callback != NULL)
(*data->callback)(tor, data->oldpath, data->newname, error, data->callback_user_data);
/* cleanup */
tr_free (data);
}
void
tr_torrentRename (tr_torrent * tor,
const char * newname,
tr_torrent_rename_done_func callback,
void * callback_user_data)
{
struct rename_data * data;
data = tr_new0 (struct rename_data, 1);
data->tor = tor;
data->newname = tr_strdup (newname);
data->callback = callback;
data->callback_user_data = callback_user_data;
tr_runInEventThread (tor->session, torrentRename, data);
}

View file

@ -1109,6 +1109,9 @@ typedef void (tr_torrent_rename_done_func)(tr_torrent * torrent,
* @callback: the callback invoked when the renaming finishes, or NULL
* @callback_data: the pointer to pass in the callback's user_data arg
*
* As a special case, renaming the root file in a torrent will call
* tr_torrentRename (tor, newname).
*
* EXAMPLES
*
* Consider a tr_torrent where its
@ -1116,7 +1119,8 @@ typedef void (tr_torrent_rename_done_func)(tr_torrent * torrent,
* info.files[1].name is "frobnitz-linux/frobnitz.iso".
*
* 1. tr_torrentRenamePath (tor, "frobnitz-linux", "foo") will rename
* the "frotbnitz-linux" folder as "foo" and update files[*].name.
* the "frotbnitz-linux" folder as "foo", update info.files[*].name,
* and also call tr_torrentRename(tor,"foo").
*
* 2. tr_torrentRenamePath (tor, "frobnitz-linux/checksum", "foo") will
* rename the "frobnitz-linux/checksum" file as "foo" and update
@ -1125,8 +1129,8 @@ typedef void (tr_torrent_rename_done_func)(tr_torrent * torrent,
* RETURN
*
* Changing tr_info's contents requires a session lock, so this function
* returns asynchronously to avoid blocking. If you don't care about error
* checking, you can pass NULL as the callback and callback_user_data arg.
* returns asynchronously to avoid blocking. If you don't want to be notified
* when the function has finished, you can pass NULL as the callback arg.
*
* On success, the callback's error argument will be 0.
*
@ -1144,6 +1148,21 @@ void tr_torrentRenamePath (tr_torrent * tor,
void * callback_user_data);
/**
* @brief Changes the torrent's name.
* @see-also tr_torrentRenamePath
*
* This function changes tr_info.name.
*
* Changing tr_info's contents requires a session lock, so this function
* returns asynchronously to avoid blocking. If you don't want to be notified
* when the function has finished, you can pass NULL as the callback arg.
*/
void tr_torrentRename (tr_torrent * tor,
const char * newname,
tr_torrent_rename_done_func callback,
void * callback_user_data);
enum
{
TR_LOC_MOVING,
@ -1757,7 +1776,12 @@ struct tr_info
/* total size of the torrent, in bytes */
uint64_t totalSize;
/* the torrent's name */
/* The original name that came in this torrent's metainfo.
* This may differ from "name" if tr_torrentRename() is called.
* CLIENT CODE: NOT USE THIS FIELD. */
char * originalName;
/* The torrent's name. */
char * name;
/* Path to torrent Transmission's internal copy of the .torrent file. */

View file

@ -827,7 +827,7 @@ Session :: parseResponse( const char * json, size_t jsonLength )
else if (tr_variantDictFindInt (args, TR_KEY_id, &id) && id)
{
// let's get the updated file list
char * req = tr_strdup_printf ("{ \"arguments\": { \"fields\": [ \"files\", \"id\" ], \"ids\": %d }, \"method\": \"torrent-get\", \"tag\": %d }",
char * req = tr_strdup_printf ("{ \"arguments\": { \"fields\": [ \"files\", \"id\", \"name\" ], \"ids\": %d }, \"method\": \"torrent-get\", \"tag\": %d }",
int(id),
int(TAG_SOME_TORRENTS));
exec (req);