819 prevsrc = targets.get(abstarget) |
819 prevsrc = targets.get(abstarget) |
820 if prevsrc is not None: |
820 if prevsrc is not None: |
821 ui.warn(_('%s: not overwriting - %s collides with %s\n') % |
821 ui.warn(_('%s: not overwriting - %s collides with %s\n') % |
822 (reltarget, abssrc, prevsrc)) |
822 (reltarget, abssrc, prevsrc)) |
823 return |
823 return |
824 elif os.path.exists(reltarget): |
824 if (not opts['after'] and os.path.exists(reltarget) or |
825 if opts['force']: |
825 opts['after'] and repo.dirstate.state(abstarget) not in '?r'): |
826 os.unlink(reltarget) |
826 if not opts['force']: |
827 else: |
|
828 ui.warn(_('%s: not overwriting - file exists\n') % |
827 ui.warn(_('%s: not overwriting - file exists\n') % |
829 reltarget) |
828 reltarget) |
830 return |
829 return |
831 if ui.verbose or not exact: |
830 if not opts['after']: |
832 ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) |
831 os.unlink(reltarget) |
833 if not opts['after']: |
832 if opts['after']: |
|
833 if not os.path.exists(reltarget): |
|
834 return |
|
835 else: |
834 targetdir = os.path.dirname(reltarget) or '.' |
836 targetdir = os.path.dirname(reltarget) or '.' |
835 if not os.path.isdir(targetdir): |
837 if not os.path.isdir(targetdir): |
836 os.makedirs(targetdir) |
838 os.makedirs(targetdir) |
837 try: |
839 try: |
838 shutil.copyfile(relsrc, reltarget) |
840 shutil.copyfile(relsrc, reltarget) |
845 else: |
847 else: |
846 ui.warn(_('%s: cannot copy - %s\n') % |
848 ui.warn(_('%s: cannot copy - %s\n') % |
847 (relsrc, inst.strerror)) |
849 (relsrc, inst.strerror)) |
848 errors += 1 |
850 errors += 1 |
849 return |
851 return |
|
852 if ui.verbose or not exact: |
|
853 ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) |
850 targets[abstarget] = abssrc |
854 targets[abstarget] = abssrc |
851 repo.copy(abssrc, abstarget) |
855 repo.copy(abssrc, abstarget) |
852 copied.append((abssrc, relsrc, exact)) |
856 copied.append((abssrc, relsrc, exact)) |
|
857 |
|
858 def targetpathfn(pat, dest, srcs): |
|
859 if os.path.isdir(pat): |
|
860 if pat.endswith(os.sep): |
|
861 pat = pat[:-len(os.sep)] |
|
862 if destdirexists: |
|
863 striplen = len(os.path.split(pat)[0]) |
|
864 else: |
|
865 striplen = len(pat) |
|
866 if striplen: |
|
867 striplen += len(os.sep) |
|
868 res = lambda p: os.path.join(dest, p[striplen:]) |
|
869 elif destdirexists: |
|
870 res = lambda p: os.path.join(dest, os.path.basename(p)) |
|
871 else: |
|
872 res = lambda p: dest |
|
873 return res |
|
874 |
|
875 def targetpathafterfn(pat, dest, srcs): |
|
876 if util.patkind(pat, None)[0]: |
|
877 # a mercurial pattern |
|
878 res = lambda p: os.path.join(dest, os.path.basename(p)) |
|
879 elif len(util.canonpath(repo.root, cwd, pat)) < len(srcs[0][0]): |
|
880 # A directory. Either the target path contains the last |
|
881 # component of the source path or it does not. |
|
882 def evalpath(striplen): |
|
883 score = 0 |
|
884 for s in srcs: |
|
885 t = os.path.join(dest, s[1][striplen:]) |
|
886 if os.path.exists(t): |
|
887 score += 1 |
|
888 return score |
|
889 |
|
890 if pat.endswith(os.sep): |
|
891 pat = pat[:-len(os.sep)] |
|
892 striplen = len(pat) + len(os.sep) |
|
893 if os.path.isdir(os.path.join(dest, os.path.split(pat)[1])): |
|
894 score = evalpath(striplen) |
|
895 striplen1 = len(os.path.split(pat)[0]) |
|
896 if striplen1: |
|
897 striplen1 += len(os.sep) |
|
898 if evalpath(striplen1) > score: |
|
899 striplen = striplen1 |
|
900 res = lambda p: os.path.join(dest, p[striplen:]) |
|
901 else: |
|
902 # a file |
|
903 if destdirexists: |
|
904 res = lambda p: os.path.join(dest, os.path.basename(p)) |
|
905 else: |
|
906 res = lambda p: dest |
|
907 return res |
|
908 |
853 |
909 |
854 pats = list(pats) |
910 pats = list(pats) |
855 if not pats: |
911 if not pats: |
856 raise util.Abort(_('no source or destination specified')) |
912 raise util.Abort(_('no source or destination specified')) |
857 if len(pats) == 1: |
913 if len(pats) == 1: |
858 raise util.Abort(_('no destination specified')) |
914 raise util.Abort(_('no destination specified')) |
859 dest = pats.pop() |
915 dest = pats.pop() |
860 destdirexists = os.path.isdir(dest) |
916 destdirexists = os.path.isdir(dest) |
861 if (len(pats) > 1 or not os.path.exists(pats[0])) and not destdirexists: |
917 if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists: |
862 raise util.Abort(_('with multiple sources, destination must be an ' |
918 raise util.Abort(_('with multiple sources, destination must be an ' |
863 'existing directory')) |
919 'existing directory')) |
864 |
920 if opts['after']: |
|
921 tfn = targetpathafterfn |
|
922 else: |
|
923 tfn = targetpathfn |
|
924 copylist = [] |
865 for pat in pats: |
925 for pat in pats: |
866 if os.path.isdir(pat): |
926 srcs = [] |
867 if destdirexists: |
|
868 striplen = len(os.path.split(pat)[0]) |
|
869 else: |
|
870 striplen = len(pat) |
|
871 if striplen: |
|
872 striplen += len(os.sep) |
|
873 targetpath = lambda p: os.path.join(dest, p[striplen:]) |
|
874 elif destdirexists: |
|
875 targetpath = lambda p: os.path.join(dest, os.path.basename(p)) |
|
876 else: |
|
877 targetpath = lambda p: dest |
|
878 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts): |
927 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts): |
879 if okaytocopy(abssrc, relsrc, exact): |
928 if okaytocopy(abssrc, relsrc, exact): |
880 copy(abssrc, relsrc, targetpath(abssrc), exact) |
929 srcs.append((abssrc, relsrc, exact)) |
|
930 if not srcs: |
|
931 continue |
|
932 copylist.append((tfn(pat, dest, srcs), srcs)) |
|
933 if not copylist: |
|
934 raise util.Abort(_('no files to copy')) |
|
935 |
|
936 for targetpath, srcs in copylist: |
|
937 for abssrc, relsrc, exact in srcs: |
|
938 copy(abssrc, relsrc, targetpath(relsrc), exact) |
881 |
939 |
882 if errors: |
940 if errors: |
883 ui.warn(_('(consider using --after)\n')) |
941 ui.warn(_('(consider using --after)\n')) |
884 if len(copied) == 0: |
|
885 raise util.Abort(_('no files to copy')) |
|
886 return errors, copied |
942 return errors, copied |
887 |
943 |
888 def copy(ui, repo, *pats, **opts): |
944 def copy(ui, repo, *pats, **opts): |
889 """mark files as copied for the next commit |
945 """mark files as copied for the next commit |
890 |
946 |