Skip to content

Conversation

@arvidn
Copy link
Owner

@arvidn arvidn commented Jan 14, 2026

No description provided.

@arvidn arvidn force-pushed the part-file-save-path branch 3 times, most recently from b7d78ea to adc0235 Compare January 18, 2026 21:20
@arvidn arvidn marked this pull request as ready for review January 19, 2026 01:15
@arvidn
Copy link
Owner Author

arvidn commented Jan 19, 2026

Responding to #7194 (comment)

@cheater

Yes, you make a good point. A relative path makes more sense.

@cheater
Copy link

cheater commented Jan 19, 2026

would it be possible for you to make it default to .parts ? if everyone has a different directory it'll be annoying when bug reports happen.

in fact i would honestly suggest just hardcoding it to .parts

@arvidn
Copy link
Owner Author

arvidn commented Jan 19, 2026

would it be possible for you to make it default to .parts ? if everyone has a different directory it'll be annoying when bug reports happen.

in fact i would honestly suggest just hardcoding it to .parts

Then it would break backwards compatibility. part files for torrents downloaded with the previous version would not be picked up.

@arvidn arvidn force-pushed the part-file-save-path branch from adc0235 to d21bed8 Compare January 19, 2026 16:00
@cheater
Copy link

cheater commented Jan 19, 2026

Oh, I think we misunderstood each other.

I would still suggest being able to turn the utilization of a subdir on and off, however:

  • default the subdir path to '.parts', so that when it's turned on the first time, that's the value that it gets
  • better yet, make the subdir path not configurable, and always make it '.parts', while also still allowing turning it on and off, and defaulting it to off

@arvidn
Copy link
Owner Author

arvidn commented Jan 19, 2026

the way this feature is "turned off" right now (in this patch) is to leave the part_file_dir an empty string. I would imagine qBT could have a default set to .parts, or something like that. But they would also know whether a torrent is being added for the first time, or whether an existing torrent is loaded from resume data (in which case it would have to use an empty string, to be backwards compatible).

@cheater
Copy link

cheater commented Jan 19, 2026

I strongly suggest making part_file_dir non-configurable:

  • not a string, but a constant
  • not configurable in the UI
  • the state for whether a part file is being used with a specific torrent would be a boolean, and not an empty check on the string
  • instead of having a variable part_file_dir that contains the subdir name, have a constant PART_FILE_DIR = ".part" and a variable part_file_dir_used that's a boolean

The reasons for that are as follows:

What do we win by making this configurable? Honestly, nothing that I can see. One could say it's for customization but we weren't able to customize the names of the parts files either and they were just being spewed into the save directory, so this is better in every way even without customization.

What do we lose?

  • The code is more complicated (empty string checks, etc), more to go wrong and for bugs to happen
  • What do you do if one torrent has one part_file_dir and another one has another part_file_dir? How do you import both into the same instance of qBt running? How do you represent the difference?
  • People showing up with weird inscrutable bugs, and now we always have to ask "did you use a weird custom part_file_dir?"
  • Another piece of customization to keep in mind when debugging
  • What are the security implications here? I don't know, and we don't want to have to think about that
  • probably a bunch more stuff but I'm on the run :)

@cheater
Copy link

cheater commented Jan 19, 2026

oh also, when initializing, checking a boolean is loads faster than checking if a string is empty... especially with thousands of torrents, that will help

@arvidn
Copy link
Owner Author

arvidn commented Jan 19, 2026

What do we win by making this configurable?

Backwards compatibility

oh also, when initializing, checking a boolean is loads faster than checking if a string is empty

I don't believe you. But even if it's slightly faster, it makes no difference in this context.

The code is more complicated (empty string checks, etc), more to go wrong and for bugs to happen

Very marginally. The complicated parts are not related to these checks. Can you point out some specific complexity in this patch that you're concerned about?

What do you do if one torrent has one part_file_dir and another one has another part_file_dir?

Their respective part files are stored in different directories. The name of that directory is stored in the resume data though.

@cheater
Copy link

cheater commented Jan 19, 2026

Backwards compatibility

I think you misunderstood me.

I suggest making it possible to turn using subdirs on and off and default to off. That ensures backwards compatibility like you want.

Configuring the name of the subdir does not provide any backwards compatibility, since currently there is no subdir at all.

I suggest making the name of the subdir NOT configurable, hardcode it, and decide whether it's being used by using a boolean flag. The flag is what makes it backwards compatible.

@glassez
Copy link
Contributor

glassez commented Jan 19, 2026

@cheater
So it turns out that you're just suggesting changing it from one hardcoded option that you don't like to another hardcoded option that you like.
Well, tomorrow there will be another "cheater" who will not like your option, and he will start all this nonsense from the beginning. It doesn't look so good.

I still think that since we've already gotten into this, we need to make it as flexible as possible (as I mentioned, just let you set both relative and absolute paths). This still does not oblige the frontend application to provide all these possibilities to the user, but it at least makes it easier to further modify this behavior if necessary (without having to make new changes to libtorrent, which is much more difficult to do).

@cheater
Copy link

cheater commented Jan 19, 2026

So it turns out that you're just suggesting changing it from one hardcoded option that you don't like to another hardcoded option that you like.

What? No. You probably came up with this and then didn't read my messages properly. I explain it three times.

Let me explain it in another way that frames things the way that you frame it.

I suggest:

  • make it possible to switch from using a subdir or not (boolean flag)
  • make the subdir name hard coded to ".parts" if it is used
  • use no subdir name if it is not used
  • default to it not being used for compatibility
  • let the user turn it on or off using a checkbox in the UI

I'm not asking to "change from one hardcoded setting to another".

This still does not oblige the frontend application to provide all these possibilities to the user

Front-end validation is a bug introducing antipattern. I've been trying to explain this earlier on. The choices should be limited by the data structures in use, not by the front end UI. This means that data on disk cannot assume values that would be impossible to represent with the UI.

@arvidn
Copy link
Owner Author

arvidn commented Jan 19, 2026

So it turns out that you're just suggesting changing it from one hardcoded option that you don't like to another hardcoded option that you like.

What? No.

The ".parts" directory name you suggested is the hard coded option.

I'm not asking to "change from one hardcoded setting to another".

You're suggesting adding another hard coded name, after saying you don't like the first hard coded name. I believe @glassez's point is that someone else may have an equally strong argument for a different name, and then we have 3 hardcoded options. and so on.

Front-end validation is a bug introducing antipattern.

You say this, but you don't really make a case for it. Compare it to other APIs. open() lets you specify the filename you want to open. Does that make it error prone, because you might chose the wrong file?

@arvidn arvidn force-pushed the part-file-save-path branch from d21bed8 to c2096bb Compare January 19, 2026 19:59
@cheater
Copy link

cheater commented Jan 19, 2026

Hey man, I don't think you understand what front-end validation means when talking about bad patterns ... anyways, don't worry about it. Do what you want. I don't care if the subdir is called ".parts", "smurfs", "vodka", or anything else. I was just trying to save people a future headache, but nvm.

@arvidn
Copy link
Owner Author

arvidn commented Jan 19, 2026

a client of a shared library isn't necessarily a "front-end".

@glassez
Copy link
Contributor

glassez commented Jan 20, 2026

Hey man, I don't think you understand what front-end validation means when talking about bad patterns ... anyways, don't worry about it.

It's you who talk about "front-end validation" so you could clarify what you mean.

I just said that it's a good idea to have library flexibly configurable (in those aspects where it doesn't require unnecessary complexity).
On the one hand, it allows the library developer to operate only with basic abstract concepts, not caring about the tasks of the UI, and on the other hand, it allows developers of all kinds of UI and middleware using this library to implement the behavior that they consider necessary, and easily change it without requiring changes to the library (what to do much more difficult, longer, if at all acceptable in some cases due to compatibility issues with other software using it).
Having the limited capabilities provided by the lower level (library), you often end up with what you have without being able to do something more advanced at the application level.

@cheater
As a qBittorrent user, the above should not concern you at all. After all, qBittorrent can implement such behavior as you suggest (just a checkbox in the settings), on top of the more advanced libtorrent feature. And I think this is a great pattern.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds a configurable subdirectory path for part files in torrents. Part files store partial pieces for files with zero priority, and previously they were always stored directly in the download directory. This feature allows users to organize these part files into a subdirectory.

Changes:

  • Added part_file_dir field to add_torrent_params to specify a relative subdirectory path for part files
  • Updated storage implementations (posix_storage and mmap_storage) to handle the custom part file directory
  • Added serialization/deserialization support for the new field in resume data
  • Updated Python bindings to expose the new field

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
include/libtorrent/add_torrent_params.hpp Added part_file_dir field with documentation
include/libtorrent/storage_defs.hpp Added part_file_dir parameter to storage_params constructor, changed path to string_view
include/libtorrent/aux_/torrent.hpp Added m_part_file_dir member variable
include/libtorrent/aux_/posix_storage.hpp Added m_part_file_dir member to posix_storage
include/libtorrent/aux_/mmap_storage.hpp Added m_part_file_dir member to mmap_storage
include/libtorrent/aux_/storage_utils.hpp Updated delete_files signature to take full part file path
src/torrent.cpp Initialize and validate m_part_file_dir, updated debug logging
src/session_handle.cpp Added validation that part_file_dir is not an absolute path
src/posix_storage.cpp Implemented part file directory handling in all operations
src/mmap_storage.cpp Implemented part file directory handling in all operations
src/storage_utils.cpp Updated delete_files to accept full part file path
src/write_resume_data.cpp Added serialization of part_file_dir
src/read_resume_data.cpp Added deserialization of part_file_dir
src/create_torrent.cpp Added empty part_file_dir parameter to storage_params construction
test/test_storage.cpp Added comprehensive tests for part file directory functionality and move operations
test/test_read_resume.cpp Added roundtrip test for part_file_dir
test/test_disk_io.cpp Added empty part_file_dir parameter
test/make_torrent.cpp Added empty part_file_dir parameter
tools/disk_io_stress_test.cpp Added empty part_file_dir parameter
examples/connection_tester.cpp Added empty part_file_dir parameter
bindings/python/src/session.cpp Added Python binding support for part_file_dir
ChangeLog Documented the new feature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@arvidn arvidn force-pushed the part-file-save-path branch from 7ab44d4 to 7fb193f Compare January 23, 2026 23:40
@arvidn arvidn merged commit 6d4e2cc into master Jan 24, 2026
45 of 48 checks passed
@arvidn arvidn deleted the part-file-save-path branch January 24, 2026 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants