mercurial/commands.py
changeset 1512 53ad6ee6ede4
parent 1507 cd8fadd8c689
child 1513 5c3b93b244aa
equal deleted inserted replaced
1511:a91bfbbe88d3 1512:53ad6ee6ede4
   785         repo.commit(files, message, opts['user'], opts['date'], match)
   785         repo.commit(files, message, opts['user'], opts['date'], match)
   786     except ValueError, inst:
   786     except ValueError, inst:
   787         raise util.Abort(str(inst))
   787         raise util.Abort(str(inst))
   788 
   788 
   789 def docopy(ui, repo, pats, opts):
   789 def docopy(ui, repo, pats, opts):
   790     if not pats:
   790     cwd = repo.getcwd()
   791         raise util.Abort(_('no source or destination specified'))
   791     errors = 0
   792     elif len(pats) == 1:
   792     copied = []
   793         raise util.Abort(_('no destination specified'))
       
   794     pats = list(pats)
       
   795     dest = pats.pop()
       
   796     sources = []
       
   797     dir2dir = len(pats) == 1 and os.path.isdir(pats[0])
       
   798 
   793 
   799     def okaytocopy(abs, rel, exact):
   794     def okaytocopy(abs, rel, exact):
   800         reasons = {'?': _('is not managed'),
   795         reasons = {'?': _('is not managed'),
   801                    'a': _('has been marked for add')}
   796                    'a': _('has been marked for add')}
   802         reason = reasons.get(repo.dirstate.state(abs))
   797         reason = reasons.get(repo.dirstate.state(abs))
   803         if reason:
   798         if reason:
   804             if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
   799             if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
   805         else:
   800         else:
   806             return True
   801             return True
   807 
   802 
   808     for src, abs, rel, exact in walk(repo, pats, opts):
   803     def copy(abssrc, relsrc, target, exact):
   809         if okaytocopy(abs, rel, exact):
   804         abstarget = util.canonpath(repo.root, cwd, target)
   810             sources.append((abs, rel, exact))
   805         reltarget = util.pathto(cwd, abstarget)
   811     if not sources:
   806         if not opts['force'] and repo.dirstate.state(abstarget) not in 'a?':
   812         raise util.Abort(_('no files to copy'))
   807             ui.warn(_('%s: not overwriting - file already managed\n') %
   813 
   808                     reltarget)
   814     cwd = repo.getcwd()
   809             return
   815     absdest = util.canonpath(repo.root, cwd, dest)
   810         if ui.verbose or not exact:
   816     reldest = util.pathto(cwd, absdest)
   811             ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
   817     if os.path.exists(reldest):
       
   818         destisfile = not os.path.isdir(reldest)
       
   819     else:
       
   820         destisfile = not dir2dir and (len(sources) == 1
       
   821                                       or repo.dirstate.state(absdest) != '?')
       
   822 
       
   823     if destisfile and len(sources) > 1:
       
   824         raise util.Abort(_('with multiple sources, destination must be a '
       
   825                            'directory'))
       
   826 
       
   827     srcpfxlen = 0
       
   828     if dir2dir:
       
   829         srcpfx = util.pathto(cwd, util.canonpath(repo.root, cwd, pats[0]))
       
   830         if os.path.exists(reldest):
       
   831             srcpfx = os.path.split(srcpfx)[0]
       
   832         if srcpfx:
       
   833             srcpfx += os.sep
       
   834         srcpfxlen = len(srcpfx)
       
   835 
       
   836     errs, copied = 0, []
       
   837     for abs, rel, exact in sources:
       
   838         if destisfile:
       
   839             mydest = reldest
       
   840         elif dir2dir:
       
   841             mydest = os.path.join(dest, rel[srcpfxlen:])
       
   842         else:
       
   843             mydest = os.path.join(dest, os.path.basename(rel))
       
   844         myabsdest = util.canonpath(repo.root, cwd, mydest)
       
   845         myreldest = util.pathto(cwd, myabsdest)
       
   846         if not opts['force'] and repo.dirstate.state(myabsdest) not in 'a?':
       
   847             ui.warn(_('%s: not overwriting - file already managed\n') % myreldest)
       
   848             continue
       
   849         mydestdir = os.path.dirname(myreldest) or '.'
       
   850         if not opts['after']:
   812         if not opts['after']:
       
   813             targetdir = os.path.dirname(reltarget) or '.'
       
   814             if not os.path.isdir(targetdir):
       
   815                 os.makedirs(targetdir)
   851             try:
   816             try:
   852                 if dir2dir: os.makedirs(mydestdir)
   817                 shutil.copyfile(relsrc, reltarget)
   853                 elif not destisfile: os.mkdir(mydestdir)
   818                 shutil.copymode(relsrc, reltarget)
   854             except OSError, inst:
       
   855                 if inst.errno != errno.EEXIST: raise
       
   856         if ui.verbose or not exact:
       
   857             ui.status(_('copying %s to %s\n') % (rel, myreldest))
       
   858         if not opts['after']:
       
   859             try:
       
   860                 shutil.copyfile(rel, myreldest)
       
   861                 shutil.copymode(rel, myreldest)
       
   862             except shutil.Error, inst:
   819             except shutil.Error, inst:
   863                 raise util.Abort(str(inst))
   820                 raise util.Abort(str(inst))
   864             except IOError, inst:
   821             except IOError, inst:
   865                 if inst.errno == errno.ENOENT:
   822                 if inst.errno == errno.ENOENT:
   866                     ui.warn(_('%s: deleted in working copy\n') % rel)
   823                     ui.warn(_('%s: deleted in working copy\n') % relsrc)
   867                 else:
   824                 else:
   868                     ui.warn(_('%s: cannot copy - %s\n') % (rel, inst.strerror))
   825                     ui.warn(_('%s: cannot copy - %s\n') %
   869                 errs += 1
   826                             (relsrc, inst.strerror))
   870                 continue
   827                     errors += 1
   871         repo.copy(abs, myabsdest)
   828                     return
   872         copied.append((abs, rel, exact))
   829         repo.copy(abssrc, abstarget)
   873     if errs:
   830         copied.append((abssrc, relsrc, exact))
       
   831 
       
   832     pats = list(pats)
       
   833     if not pats:
       
   834         raise util.Abort(_('no source or destination specified'))
       
   835     if len(pats) == 1:
       
   836         raise util.Abort(_('no destination specified'))
       
   837     dest = pats.pop()
       
   838     destdirexists = os.path.isdir(dest)
       
   839     if (len(pats) > 1 or not os.path.exists(pats[0])) and not destdirexists:
       
   840         raise util.Abort(_('with multiple sources, destination must be an '
       
   841                          'existing directory'))
       
   842 
       
   843     for pat in pats:
       
   844         if os.path.isdir(pat):
       
   845             if destdirexists:
       
   846                 striplen = len(os.path.split(pat)[0])
       
   847             else:
       
   848                 striplen = len(pat)
       
   849             if striplen:
       
   850                 striplen += len(os.sep)
       
   851             targetpath = lambda p: os.path.join(dest, p[striplen:])
       
   852         elif destdirexists:
       
   853             targetpath = lambda p: os.path.join(dest, os.path.basename(p))
       
   854         else:
       
   855             targetpath = lambda p: dest
       
   856         for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
       
   857             if okaytocopy(abssrc, relsrc, exact):
       
   858                 copy(abssrc, relsrc, targetpath(abssrc), exact)
       
   859 
       
   860     if errors:
   874         ui.warn(_('(consider using --after)\n'))
   861         ui.warn(_('(consider using --after)\n'))
   875     return errs, copied
   862     if len(copied) == 0:
       
   863         raise util.Abort(_('no files to copy'))
       
   864     return errors, copied
   876 
   865 
   877 def copy(ui, repo, *pats, **opts):
   866 def copy(ui, repo, *pats, **opts):
   878     """mark files as copied for the next commit
   867     """mark files as copied for the next commit
   879 
   868 
   880     Mark dest as having copies of source files.  If dest is a
   869     Mark dest as having copies of source files.  If dest is a