There's enough changes here that we do need rigorous review.
The previous patch saw copy-onto-self and bailed out early -but these checks were made before the destination path was fully generated -because if you specify a destination directory, the source goes in under there. Which means you could set the dest dir to be the parent of the source file, so generating a rename(src, src) after the equality check had taken place -a rename that would return false.
Now the value is checked once up front -for fast exit without talking to S3, and then just before the operation actually takes place.
I also added lots of inline comments to make it clearer what is going on.